public OBBCoords?GetOBBCoord(Vector3D worldPosition) { int index = 0; while (index < this.m_obbs.Length) { int num2 = 0; while (true) { if (num2 >= this.m_obbs[0].Length) { index++; break; } MyOrientedBoundingBoxD xd = this.m_obbs[index][num2].Value; if (xd.Contains(ref worldPosition)) { return(new OBBCoords?(new OBBCoords { OBB = xd, Coords = new Vector2I(index, num2) })); } num2++; } } return(null); }
public MyOrientedBoundingBoxD?GetOBB(Vector3D worldPosition) { MyOrientedBoundingBoxD?[][] obbs = this.m_obbs; int index = 0; while (index < obbs.Length) { MyOrientedBoundingBoxD?[] nullableArray2 = obbs[index]; int num2 = 0; while (true) { if (num2 >= nullableArray2.Length) { index++; break; } MyOrientedBoundingBoxD?nullable = nullableArray2[num2]; MyOrientedBoundingBoxD xd = nullable.Value; if (xd.Contains(ref worldPosition)) { return(nullable); } num2++; } } return(null); }
public static unsafe void DisableItemsInObb(this MyEnvironmentSector sector, ref MyOrientedBoundingBoxD obb) { if (sector.DataView == null) { return; } obb.Center -= sector.SectorCenter; for (int sectorInd = 0; sectorInd < sector.DataView.LogicalSectors.Count; sectorInd++) { var logicalSector = sector.DataView.LogicalSectors[sectorInd]; var logicalItems = logicalSector.Items; var cnt = logicalItems.Count; fixed(ItemInfo *items = logicalItems.GetInternalArray()) for (int i = 0; i < cnt; ++i) { if (items[i].DefinitionIndex >= 0 && obb.Contains(ref items[i].Position)) { logicalSector.EnableItem(i, false); } } } }
public static bool IsPositionInSafeZone(Vector3D position) { foreach (var safezone in safezoneList) { var zoneEntity = safezone as IMyEntity; var checkPosition = position; bool inZone = false; if (safezone.Shape == MySafeZoneShape.Sphere) { if (zoneEntity.PositionComp.WorldVolume.Contains(checkPosition) == ContainmentType.Contains) { inZone = true; } } else { MyOrientedBoundingBoxD myOrientedBoundingBoxD = new MyOrientedBoundingBoxD(zoneEntity.PositionComp.LocalAABB, zoneEntity.PositionComp.WorldMatrix); inZone = myOrientedBoundingBoxD.Contains(ref checkPosition); } if (inZone == true) { return(true); } } return(false); }
private bool OriginalSpotClear() { List <MyEntity> entities = new List <MyEntity>(); MyGamePruningStructure.GetAllEntitiesInOBB(ref BoxD, entities); bool SpotCleared = true; foreach (var entity in entities.OfType <MyCubeGrid>()) { MyOrientedBoundingBoxD OBB = new MyOrientedBoundingBoxD(entity.PositionComp.LocalAABB, entity.WorldMatrix); ContainmentType Type = BoxD.Contains(ref OBB); //Log.Info($"{entity.DisplayName} Type: {Type.ToString()}"); if (Type == ContainmentType.Contains || Type == ContainmentType.Intersects) { SpotCleared = false; _Response.Respond("There are potentially other grids in the way. Attempting to spawn around the location to avoid collisions."); break; } } return(SpotCleared); }
private static bool HasBlocksInside(MyCubeGrid grid, ref MyOrientedBoundingBoxD obb) { Vector3I center = grid.WorldToGridInteger(obb.Center); double radius = obb.HalfExtent.Length(); radius *= grid.GridSizeR; Vector3I gridMin = grid.Min; Vector3I gridMax = grid.Max; double radiusSq = radius * radius; int radiusCeil = (int)Math.Ceiling(radius); BoundingSphereD cubeSphere = new BoundingSphereD(new Vector3D(), grid.GridSizeHalf * Math.Sqrt(3)); Vector3I max = Vector3I.Min(Vector3I.One * radiusCeil, gridMax - center); Vector3I min = Vector3I.Max(Vector3I.One * -radiusCeil, gridMin - center); int x, y, z; for (x = min.X; x <= max.X; ++x) { for (y = min.Y; y <= max.Y; ++y) { for (z = min.Z; z <= max.Z; ++z) { if (x * x + y * y + z * z >= radiusSq) { continue; } Vector3I offset = new Vector3I(x, y, z); Vector3I cubePos = center + offset; MyCube cube; if (!grid.TryGetCube(cubePos, out cube)) { continue; } IMySlimBlock slim = cube.CubeBlock; if (slim.IsDestroyed) { continue; } cubeSphere.Center = grid.GridIntegerToWorld(cubePos); if (obb.Contains(ref cubeSphere) != ContainmentType.Disjoint) { return(true); } } } } return(false); }
private static bool IsAllowed(MySafeZone safezone, MyOrientedBoundingBoxD obb, IMyEntity original = null) { if (!safezone.Enabled) { return(true); } if (safezone.AccessTypeGrids == Sandbox.Common.ObjectBuilders.MySafeZoneAccess.Whitelist) { return(false); } if (safezone.Shape == Sandbox.Common.ObjectBuilders.MySafeZoneShape.Box) { var zoneOBB = new MyOrientedBoundingBoxD(safezone.PositionComp.LocalAABB, safezone.PositionComp.WorldMatrixRef); if (obb.Contains(ref zoneOBB) == ContainmentType.Disjoint) { return(true); } } else { var zoneSphere = new BoundingSphereD(safezone.PositionComp.GetPosition(), safezone.Radius); if (obb.Contains(ref zoneSphere) == ContainmentType.Disjoint) { return(true); } } // 512 = VRage.Game.ObjectBuilders.Components.MySafeZoneAction.BuildingProjections if (original == null) { return(safezone.IsActionAllowed(obb.GetAABB(), CastProhibit(safezone.AllowedActions, 512))); } return(safezone.IsActionAllowed((MyEntity)original, CastProhibit(safezone.AllowedActions, 512))); }
//IsPositionInSafeZone public static bool IsPositionInSafeZone(Vector3D position) { var zones = GetSafeZones(); foreach (var safezone in zones) { var zoneEntity = safezone as IMyEntity; if (zoneEntity == null) { continue; } if (safezone.Enabled == false) { continue; } var checkPosition = position; bool inZone = false; if (safezone.Shape == MySafeZoneShape.Sphere) { if (Vector3D.Distance(zoneEntity.PositionComp.WorldVolume.Center, position) < safezone.Radius) { inZone = true; } } else { MyOrientedBoundingBoxD myOrientedBoundingBoxD = new MyOrientedBoundingBoxD(zoneEntity.PositionComp.LocalAABB, zoneEntity.PositionComp.WorldMatrix); inZone = myOrientedBoundingBoxD.Contains(ref checkPosition); } if (inZone == true) { return(true); } } return(false); }
private unsafe void DisableOtherItemsInVMap(MyVoxelBase voxelMap) { MyOrientedBoundingBoxD obb = MyOrientedBoundingBoxD.Create((BoundingBoxD)voxelMap.PositionComp.LocalAABB, voxelMap.PositionComp.WorldMatrix); var center = obb.Center; var box = voxelMap.PositionComp.WorldAABB; m_entities.Clear(); MyGamePruningStructure.GetAllEntitiesInBox(ref box, m_entities, MyEntityQueryType.Static); for (int eIndex = 0; eIndex < m_entities.Count; ++eIndex) { var sector = m_entities[eIndex] as MyEnvironmentSector; if (sector == null || sector.DataView == null) { continue; } obb.Center = center - sector.SectorCenter; for (int sectorInd = 0; sectorInd < sector.DataView.LogicalSectors.Count; sectorInd++) { var logicalSector = sector.DataView.LogicalSectors[sectorInd]; var logicalItems = logicalSector.Items; var cnt = logicalItems.Count; fixed(ItemInfo *items = logicalItems.GetInternalArray()) for (int i = 0; i < cnt; ++i) { var point = items[i].Position + sector.SectorCenter; if (items[i].DefinitionIndex >= 0 && obb.Contains(ref items[i].Position) && voxelMap.CountPointsInside(&point, 1) > 0 && !IsVoxelItem(sector, items[i].DefinitionIndex)) { logicalSector.EnableItem(i, false); } } } } }
/// <summary> /// Calculates amount of volume of a bounding box in voxels. /// </summary> /// <param name="localAabb">Local bounding box to query for.</param> /// <param name="worldMatrix">World matrix of the bounding box.</param> /// <returns>Pair of floats where 1st value is Volume amount and 2nd value is ratio of Volume amount to Whole volume.</returns> public MyTuple <float, float> GetVoxelContentInBoundingBox_Fast(BoundingBoxD localAabb, MatrixD worldMatrix) { MatrixD toVoxel = worldMatrix * PositionComp.WorldMatrixNormalizedInv; MatrixD toGrid; MatrixD.Invert(ref toVoxel, out toGrid); BoundingBoxD transAABB = localAabb.Transform(toVoxel); transAABB.Translate(SizeInMetresHalf + StorageMin); Vector3I minI = Vector3I.Floor(transAABB.Min); Vector3I maxI = Vector3I.Ceiling(transAABB.Max); double vol = localAabb.Volume / MyVoxelConstants.VOXEL_VOLUME_IN_METERS; int K = Math.Max((MathHelper.Log2Ceiling((int)vol) - MathHelper.Log2Ceiling(100)) / 3, 0); float voxelSizeAtLod = MyVoxelConstants.VOXEL_SIZE_IN_METRES * (1 << K); float voxelVolumeAtLod = voxelSizeAtLod * voxelSizeAtLod * voxelSizeAtLod; minI >>= K; maxI >>= K; // localAabb.Inflate(1 * voxelSizeAtLod); var offset = ((Size >> 1) + StorageMin) >> K; m_tempStorage.Resize(maxI - minI + 1); Storage.ReadRange(m_tempStorage, MyStorageDataTypeFlags.Content, K, minI, maxI); float resultVolume = 0; float resultPercent = 0; int hitVolumeBoxes = 0; MyOrientedBoundingBoxD worldbbox = new MyOrientedBoundingBoxD(localAabb, worldMatrix); Vector3I coord, cache; for (coord.Z = minI.Z, cache.Z = 0; coord.Z <= maxI.Z; coord.Z++, cache.Z++) { for (coord.Y = minI.Y, cache.Y = 0; coord.Y <= maxI.Y; coord.Y++, cache.Y++) { for (coord.X = minI.X, cache.X = 0; coord.X <= maxI.X; coord.X++, cache.X++) { Vector3D voxelPos = (coord - offset) * voxelSizeAtLod; Vector3D gridPoint; Vector3D.Transform(ref voxelPos, ref toGrid, out gridPoint); ContainmentType cont; //localAabb.Contains(ref gridPoint, out cont); var voxelToWorld = WorldMatrix; voxelToWorld.Translation -= (Vector3D)StorageMin + SizeInMetresHalf; BoundingBoxD voxelBox = new BoundingBoxD(); voxelBox.Min = ((Vector3D)(coord) - .5) * voxelSizeAtLod; voxelBox.Max = ((Vector3D)(coord) + .5) * voxelSizeAtLod; MyOrientedBoundingBoxD voxelBbox = new MyOrientedBoundingBoxD(voxelBox, voxelToWorld); cont = worldbbox.Contains(ref voxelBbox); if (cont == ContainmentType.Disjoint) { //VRageRender.MyRenderProxy.DebugDrawOBB( //new MyOrientedBoundingBoxD(voxelBox, voxelToWorld), Color.Red, 0.1f, //true, false); continue; } float content = m_tempStorage.Content(ref cache) / MyVoxelConstants.VOXEL_CONTENT_FULL_FLOAT; //VRageRender.MyRenderProxy.DebugDrawOBB(voxelBbox, Color.Aqua, content, // true, false); resultVolume += content * voxelVolumeAtLod; resultPercent += content; hitVolumeBoxes++; } } } resultPercent /= hitVolumeBoxes; //float localAABBVol = (float)localAabb.Volume; //if (localAABBVol < resultVolume) // resultPercent *= (float)localAabb.Volume / resultVolume; //VRageRender.MyRenderProxy.DebugDrawOBB(worldbbox, Color.Yellow, 0, // true, false); //VRageRender.MyRenderProxy.DebugWaitForFrameFinish(); return(new MyTuple <float, float>(resultVolume, resultPercent)); }
/// <summary> /// Handles camera collisions with environment /// </summary> /// <returns>False if no correct position was found</returns> private void HandleIntersection(MyEntity controlledEntity) { Debug.Assert(controlledEntity != null); MyEntity parentEntity = controlledEntity.GetTopMostParent() ?? controlledEntity; var parentEntityAsCubeGrid = parentEntity as MyCubeGrid; if (parentEntityAsCubeGrid != null && parentEntityAsCubeGrid.IsStatic) { parentEntity = controlledEntity; // cancel previous assignment, topmost parent is a station, we need smaller bounding box } // line from target to eye LineD line = new LineD(m_target, m_position); // oriented bb of the entity MyOrientedBoundingBoxD safeObb = GetEntitySafeOBB(parentEntity); // oriented bb of the entity + camera radius MyOrientedBoundingBoxD safeObbWithCollisionExtents = new MyOrientedBoundingBoxD(safeObb.Center, safeObb.HalfExtent + (controlledEntity.Parent == null ? 0.5 : 2.0) * CAMERA_RADIUS, safeObb.Orientation); // start = target, end = eye // find safe start... LineD safeOBBLine = new LineD(line.From + line.Direction * 2 * safeObb.HalfExtent.Length(), line.From); double? safeIntersection = safeObbWithCollisionExtents.Intersects(ref safeOBBLine); Vector3D castStartSafe = safeIntersection != null ? (safeOBBLine.From + safeOBBLine.Direction * safeIntersection.Value) : m_target; if (controlledEntity.Parent != null && safeIntersection != null) { MatrixD shapeCastStart = MatrixD.CreateTranslation(castStartSafe); HkShape hkSphere = new HkSphereShape(CAMERA_RADIUS * 2); var hitInfo = MyPhysics.CastShapeReturnContactBodyData(m_target, hkSphere, ref shapeCastStart, 0, 0); //VRageRender.MyRenderProxy.DebugDrawCapsule(castStartSafe, m_target, CAMERA_RADIUS * 2, Color.Orange, false); MyEntity hitEntity = hitInfo.HasValue ? hitInfo.Value.HkHitInfo.GetHitEntity() as MyEntity : null; MyEntity entity = controlledEntity; var hitEntityWeldingGroup = hitEntity != null?MyWeldingGroups.Static.GetGroup(hitEntity) : null; bool weldingGroupEquals = false; while (entity != null && !weldingGroupEquals) { if (hitEntityWeldingGroup == MyWeldingGroups.Static.GetGroup(entity)) { weldingGroupEquals = true; } entity = entity.Parent; } if (hitInfo.HasValue && hitEntityWeldingGroup != null && weldingGroupEquals) { castStartSafe = castStartSafe + hitInfo.Value.HkHitInfo.HitFraction * (m_target - castStartSafe); } else { safeObb = GetEntitySafeOBB(controlledEntity); safeObbWithCollisionExtents = new MyOrientedBoundingBoxD(safeObb.Center, safeObb.HalfExtent + 0.5f * CAMERA_RADIUS, safeObb.Orientation); safeIntersection = safeObbWithCollisionExtents.Intersects(ref safeOBBLine); castStartSafe = safeIntersection != null ? (safeOBBLine.From + safeOBBLine.Direction * safeIntersection.Value) : m_target; } hkSphere.RemoveReference(); } // raycast against occluders Vector3D safePositionCandidate; //double lastSafeMinimumDistance = m_safeMinimumDistance; m_safeMinimumDistance = controlledEntity is MyCharacter ? 0 : (castStartSafe - m_target).Length(); // store current safe minimum dist m_safeMinimumDistance = Math.Max(m_safeMinimumDistance, MIN_VIEWER_DISTANCE); //if (lastSafeMinimumDistance + 30.0f < m_safeMinimumDistance) //{ // castStartSafe = m_target + (castStartSafe - m_target) / m_safeMinimumDistance * lastSafeMinimumDistance; // m_safeMinimumDistance = lastSafeMinimumDistance; //} Vector3D raycastOrigin = (controlledEntity is MyCharacter) ? m_target : castStartSafe; MyCameraRaycastResult raycastResult = RaycastOccludingObjects(controlledEntity, ref raycastOrigin, ref m_position, ref castStartSafe, out safePositionCandidate); if (controlledEntity is MyCharacter && safeObb.Contains(ref safePositionCandidate)) { raycastResult = MyCameraRaycastResult.FoundOccluderNoSpace; } // visual debugging :) if (m_debugDraw) { VRageRender.MyRenderProxy.DebugDrawOBB(safeObb, Color.Red, 0.1f, false, true); VRageRender.MyRenderProxy.DebugDrawOBB(safeObbWithCollisionExtents, Color.Yellow, 0.0f, false, true); VRageRender.MyRenderProxy.DebugDrawArrow3D(safeOBBLine.From, safeOBBLine.To, Color.White, Color.Purple, false); VRageRender.MyRenderProxy.DebugDrawArrow3D(safeOBBLine.From, castStartSafe, Color.White, Color.Red, false); VRageRender.MyRenderProxy.DebugDrawArrow3D(castStartSafe, m_position, Color.White, Color.Orange, false); VRageRender.MyRenderProxy.DebugDrawSphere(castStartSafe, 0.2f, Color.Green, 1.0f, false, true); VRageRender.MyRenderProxy.DebugDrawSphere(safePositionCandidate, 1.0f, Color.LightPink, 1, false); } switch (raycastResult) { case MyCameraRaycastResult.Ok: case MyCameraRaycastResult.FoundOccluder: m_positionCurrentIsSafe = true; { double distFromCandidateToTarget = (safePositionCandidate - m_target).Length(); if (m_disableSpringThisFrame) { m_lastRaycastDist = (float)distFromCandidateToTarget; } if (!m_disableSpringThisFrame && ((distFromCandidateToTarget > m_lastRaycastDist + CAMERA_RADIUS && distFromCandidateToTarget > m_safeMinimumDistance) || raycastResult == MyCameraRaycastResult.Ok)) { // now we need it from the other side double newDist = (safePositionCandidate - m_position).Length(); // new safe position is further from target => change over time (zoom out) if (m_positionSafeZoomingOutTimeout <= 0) { float distDiffZoomSpeed = 1 - MathHelper.Clamp((float)Math.Abs(m_lastRaycastDist - newDist), 0.0f, 1.0f - MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS); m_positionSafeZoomingOutSpeed += distDiffZoomSpeed; m_positionSafeZoomingOutSpeed = MathHelper.Clamp(m_positionSafeZoomingOutSpeed, 0.0f, 1.0f); Vector3D targetToPosSafe = m_positionSafe - m_target; double lenTargetToPosSafe = targetToPosSafe.Length(); Vector3D rotatedPositionSafe = m_target + Vector3D.Normalize(safePositionCandidate - m_target) * lenTargetToPosSafe; m_positionSafe = Vector3D.Lerp(rotatedPositionSafe, safePositionCandidate, m_positionSafeZoomingOutSpeed); } else { m_positionSafeZoomingOutTimeout -= MyEngineConstants.UPDATE_STEP_SIZE_IN_MILLISECONDS; Vector3D targetToPosSafe = m_positionSafe - m_target; double lenTargetToPosSafe = targetToPosSafe.Length(); m_positionSafe = m_target + Vector3D.Normalize(safePositionCandidate - m_target) * lenTargetToPosSafe; } } else { // new safe position is closer or closer than safe distance => instant change m_positionSafeZoomingOutSpeed = 0.0f; // set zooming out speed to zero for next time m_positionSafeZoomingOutTimeout = 0; // controlledEntity.Parent != null ? m_positionSafeZoomingOutDefaultTimeoutMs : 0; m_positionSafe = safePositionCandidate; m_disableSpringThisFrame = true; m_positionCurrentIsSafe = distFromCandidateToTarget >= m_safeMinimumDistance; } } break; //case MyCameraRaycastResult.FoundOccluderNoSpace: default: m_positionSafeZoomingOutSpeed = 1.0f; // we're in first person, change instantly to third if possible m_positionCurrentIsSafe = false; break; } m_lastRaycastDist = (float)(m_positionSafe - m_position).Length(); if (m_debugDraw) { VRageRender.MyRenderProxy.DebugDrawSphere(m_positionSafe, 0.225f, Color.Purple, 1, false); VRageRender.MyRenderProxy.DebugDrawSphere(safePositionCandidate, 0.2f, Color.Azure, 1, false); } }
/// <summary> /// Calculates amount of volume of a bounding box in voxels. /// </summary> /// <param name="localAabb">Local bounding box to query for.</param> /// <param name="worldMatrix">World matrix of the bounding box.</param> /// <returns>Pair of floats where 1st value is Volume amount and 2nd value is ratio of Volume amount to Whole volume.</returns> public MyTuple<float,float> GetVoxelContentInBoundingBox_Fast(BoundingBoxD localAabb, MatrixD worldMatrix) { MatrixD toVoxel = worldMatrix * PositionComp.WorldMatrixNormalizedInv; MatrixD toGrid; MatrixD.Invert(ref toVoxel, out toGrid); BoundingBoxD transAABB = localAabb.TransformFast(toVoxel); transAABB.Translate(SizeInMetresHalf + StorageMin); Vector3I minI = Vector3I.Floor(transAABB.Min); Vector3I maxI = Vector3I.Ceiling(transAABB.Max); double vol = localAabb.Volume / MyVoxelConstants.VOXEL_VOLUME_IN_METERS; int K = Math.Max((MathHelper.Log2Ceiling((int)vol) - MathHelper.Log2Ceiling(100)) / 3, 0); float voxelSizeAtLod = MyVoxelConstants.VOXEL_SIZE_IN_METRES * (1 << K); float voxelVolumeAtLod = voxelSizeAtLod * voxelSizeAtLod * voxelSizeAtLod; minI >>= K; maxI >>= K; // localAabb.Inflate(1 * voxelSizeAtLod); var offset = ((Size >> 1) + StorageMin) >> K; m_tempStorage.Resize(maxI - minI + 1); Storage.ReadRange(m_tempStorage, MyStorageDataTypeFlags.Content, K, minI, maxI); float resultVolume = 0; float resultPercent = 0; int hitVolumeBoxes = 0; MyOrientedBoundingBoxD worldbbox = new MyOrientedBoundingBoxD(localAabb, worldMatrix); Vector3I coord, cache; for (coord.Z = minI.Z, cache.Z = 0; coord.Z <= maxI.Z; coord.Z++, cache.Z++) { for (coord.Y = minI.Y, cache.Y = 0; coord.Y <= maxI.Y; coord.Y++, cache.Y++) { for (coord.X = minI.X, cache.X = 0; coord.X <= maxI.X; coord.X++, cache.X++) { Vector3D voxelPos = (coord - offset) * voxelSizeAtLod; Vector3D gridPoint; Vector3D.Transform(ref voxelPos, ref toGrid, out gridPoint); ContainmentType cont; //localAabb.Contains(ref gridPoint, out cont); var voxelToWorld = WorldMatrix; voxelToWorld.Translation -= (Vector3D)StorageMin + SizeInMetresHalf; BoundingBoxD voxelBox = new BoundingBoxD(); voxelBox.Min = ((Vector3D)(coord) - .5) * voxelSizeAtLod; voxelBox.Max = ((Vector3D)(coord) + .5) * voxelSizeAtLod; MyOrientedBoundingBoxD voxelBbox = new MyOrientedBoundingBoxD(voxelBox, voxelToWorld); cont = worldbbox.Contains(ref voxelBbox); if (cont == ContainmentType.Disjoint) { //VRageRender.MyRenderProxy.DebugDrawOBB( //new MyOrientedBoundingBoxD(voxelBox, voxelToWorld), Color.Red, 0.1f, //true, false); continue; } float content = m_tempStorage.Content(ref cache) / MyVoxelConstants.VOXEL_CONTENT_FULL_FLOAT; //VRageRender.MyRenderProxy.DebugDrawOBB(voxelBbox, Color.Aqua, content, // true, false); resultVolume += content * voxelVolumeAtLod; resultPercent += content; hitVolumeBoxes++; } } } resultPercent /= hitVolumeBoxes; //float localAABBVol = (float)localAabb.Volume; //if (localAABBVol < resultVolume) // resultPercent *= (float)localAabb.Volume / resultVolume; //VRageRender.MyRenderProxy.DebugDrawOBB(worldbbox, Color.Yellow, 0, // true, false); //VRageRender.MyRenderProxy.DebugWaitForFrameFinish(); return new MyTuple<float, float>(resultVolume, resultPercent); }
public static unsafe void DisableItemsInObb(this MyEnvironmentSector sector, ref MyOrientedBoundingBoxD obb) { if (sector.DataView == null) return; obb.Center -= sector.SectorCenter; for (int sectorInd = 0; sectorInd < sector.DataView.LogicalSectors.Count; sectorInd++) { var logicalSector = sector.DataView.LogicalSectors[sectorInd]; var logicalItems = logicalSector.Items; var cnt = logicalItems.Count; fixed (ItemInfo* items = logicalItems.GetInternalArray()) for (int i = 0; i < cnt; ++i) { if (items[i].DefinitionIndex >= 0 && obb.Contains(ref items[i].Position)) logicalSector.EnableItem(i, false); } } }
static ContainmentType ContainsAdv(this MyOrientedBoundingBoxD obb, BoundingFrustumD frust, HashSet <Vector3D> internalPoints, out bool noCorners) { var points = new Vector3D[8]; obb.GetCorners(points, 0); int inside = 0; for (int i = 0; i < points.Length; i++) { if (frust.Contains(points[i]) != ContainmentType.Disjoint) { inside++; internalPoints.Add(points[i]); } } noCorners = false; switch (inside) { case (8): return(ContainmentType.Contains); default: if (internalPoints.Count != 0 || frust.Contains(obb.GetAABB()) != ContainmentType.Disjoint) { noCorners = true; var res = new HashSet <Vector3D>(); var lines = frust.GetLines(); for (int i = 0; i < lines.Length; i++) { var from = obb.Contains(ref lines[i].From); var to = obb.Contains(ref lines[i].To); if (from && to) { res.Add(lines[i].From); res.Add(lines[i].To); } else if (from) { res.Add(lines[i].From); res.Add(lines[i].GetPoint(obb.Intersects(ref lines[i]).Value)); } else if (to) { res.Add(lines[i].To); var back = lines[i].Reverse(); res.Add(back.GetPoint(obb.Intersects(ref back).Value)); } else { var first = obb.Intersects(ref lines[i]); var back = lines[i].Reverse(); var second = obb.Intersects(ref back); if (first != null) { res.Add(lines[i].GetPoint(first.Value)); } if (second != null) { res.Add(back.GetPoint(second.Value)); } } } lines = obb.GetLines(); for (int i = 0; i < lines.Length; i++) { var from = frust.Contains(lines[i].From) != ContainmentType.Disjoint; var to = frust.Contains(lines[i].To) != ContainmentType.Disjoint; if (from && to) { res.Add(lines[i].From); res.Add(lines[i].To); } else if (from) { res.Add(lines[i].From); res.Add(lines[i].GetPoint(frust.Intersects(lines[i].ToRay()).Value)); } else if (to) { res.Add(lines[i].To); res.Add(lines[i].Reverse().GetPoint(frust.Intersects(lines[i].ToReversedRay()).Value)); } else { var first = frust.Intersects(lines[i].ToRay()); var second = frust.Intersects(lines[i].ToReversedRay()); if (first != null) { res.Add(lines[i].GetPoint(first.Value)); } if (second != null) { res.Add(lines[i].Reverse().GetPoint(second.Value)); } } } foreach (var r in res) { internalPoints.Add(r); } if (internalPoints.Count > 0) { return(ContainmentType.Intersects); } } return(ContainmentType.Disjoint); } }
private void DrawActiveLeads() { var s = _session; var focus = s.TrackingAi.Construct.Data.Repo.FocusData; MyEntity target; if (!MyEntities.TryGetEntityById(focus.Target[focus.ActiveId], out target) && target.Physics == null) { return; } var targetSphere = target.PositionComp.WorldVolume; float maxLeadLength; Vector3D fullAveragePos; if (!ComputeLead(target, targetSphere.Center, out maxLeadLength, out fullAveragePos)) { return; } var lineStart = targetSphere.Center; var lineNormDir = Vector3D.Normalize(fullAveragePos - lineStart); var ray = new RayD(lineStart, lineNormDir); var rayDist = s.CameraFrustrum.Intersects(ray); if (!s.Camera.IsInFrustum(ref targetSphere) || rayDist == null) { return; } var lineEnd = lineStart + (lineNormDir * maxLeadLength); var endScreenPos = s.Camera.WorldToScreen(ref lineEnd); var worldLine = new LineD(lineEnd, lineStart, maxLeadLength); var obb = new MyOrientedBoundingBoxD(target.PositionComp.LocalAABB, target.PositionComp.WorldMatrixRef); var lineLength = obb.Intersects(ref worldLine) ?? 0; if (lineLength < 0.2f) { return; } var lineScale = (float)(0.1 * s.ScaleFov); var startScreenPos = s.Camera.WorldToScreen(ref lineStart); var scaledAspect = lineScale * _session.AspectRatio; var scale = s.Settings.ClientConfig.HudScale; var fontScale = scale * s.ScaleFov; Vector3D fursthestScreenPos = Vector3D.Zero; double furthestDist = 0; var element = 0; for (int i = 0; i < _leadInfos.Count; i++) { var info = _leadInfos[i]; if (obb.Contains(ref info.Position)) { continue; } var screenPos = s.Camera.WorldToScreen(ref info.Position); var lockedScreenPos = MyUtils.GetClosestPointOnLine(ref startScreenPos, ref endScreenPos, ref screenPos); var distSqr = Vector3D.DistanceSquared(lockedScreenPos, startScreenPos); if (distSqr > furthestDist) { furthestDist = distSqr; fursthestScreenPos = lockedScreenPos; } var textColor = !info.WillHit ? new Vector4(1, 1, 1, 1) : new Vector4(1, 0.025f, 0.025f, 1); string textLine1 = (i + 1).ToString(); var fontFocusSize = !info.WillHit ? 8 : 11; var fontSize = (float)Math.Round(fontFocusSize * fontScale, 2); var fontHeight = 0.75f; var fontAge = -1; var fontJustify = Hud.Justify.Center; var fontType = Hud.FontType.Shadow; var elementId = 2000 + element++; s.HudUi.AddText(text: textLine1, x: (float)lockedScreenPos.X, y: (float)lockedScreenPos.Y, elementId: elementId, ttl: fontAge, color: textColor, justify: fontJustify, fontType: fontType, fontSize: fontSize, heightScale: fontHeight); } var endDotPos = new Vector2D(fursthestScreenPos.X, fursthestScreenPos.Y); endDotPos.X *= scaledAspect; endDotPos.Y *= lineScale; var lineEndScreenPos = Vector3D.Transform(new Vector3D(endDotPos.X, endDotPos.Y, -0.1), s.CameraMatrix); var culledLineStart = lineEnd - (lineNormDir * lineLength); var culledStartScreenPos = s.Camera.WorldToScreen(ref culledLineStart); var culledStartDotPos = new Vector2D(culledStartScreenPos.X, culledStartScreenPos.Y); culledStartDotPos.X *= scaledAspect; culledStartDotPos.Y *= lineScale; var lineStartScreenPos = Vector3D.Transform(new Vector3D(culledStartDotPos.X, culledStartDotPos.Y, -0.1), s.CameraMatrix); var lineColor = new Vector4(0.5f, 0.5f, 1, 1); var lineMagnitude = lineEndScreenPos - lineStartScreenPos; MyTransparentGeometry.AddLineBillboard(_laserLine, lineColor, lineStartScreenPos, lineMagnitude, 1f, lineScale * 0.005f); var avgScreenPos = s.Camera.WorldToScreen(ref fullAveragePos); var avgLockedScreenPos = MyUtils.GetClosestPointOnLine(ref startScreenPos, ref endScreenPos, ref avgScreenPos); var dotpos = new Vector2D(avgLockedScreenPos.X, avgLockedScreenPos.Y); dotpos.X *= scaledAspect; dotpos.Y *= lineScale; avgLockedScreenPos = Vector3D.Transform(new Vector3D(dotpos.X, dotpos.Y, -0.1), s.CameraMatrix); var size = (float)((0.00125f * scale) * s.ScaleFov); var left = (Vector3)s.CameraMatrix.Left; var up = (Vector3)s.CameraMatrix.Up; var repColor = new Vector4(1, 1, 1, 1); var time = s.Tick % 20; // forward and backward total time var increase = time < 10; var directionalTimeStep = increase ? time : 19 - time; var textureMap = s.HudUi.PaintedTexture[directionalTimeStep]; MyQuadD quad; MyUtils.GetBillboardQuadOriented(out quad, ref avgLockedScreenPos, size, size, ref left, ref up); MyTransparentGeometry.AddTriangleBillboard(quad.Point0, quad.Point1, quad.Point2, Vector3.Zero, Vector3.Zero, Vector3.Zero, textureMap.P0, textureMap.P1, textureMap.P3, textureMap.Material, 0, avgLockedScreenPos, repColor, BlendTypeEnum.PostPP); MyTransparentGeometry.AddTriangleBillboard(quad.Point0, quad.Point3, quad.Point2, Vector3.Zero, Vector3.Zero, Vector3.Zero, textureMap.P0, textureMap.P2, textureMap.P3, textureMap.Material, 0, avgLockedScreenPos, repColor, BlendTypeEnum.PostPP); _leadInfos.Clear(); }