static BoundingBoxD GetEntityAABB(MyEntity entity) { BoundingBoxD bbox = entity.PositionComp.WorldAABB; //Include entity velocity to be able to hit fast moving objects if (entity.Physics != null) { bbox = bbox.Include(entity.WorldMatrix.Translation + entity.Physics.LinearVelocity * VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS * 5); } return(bbox); }
public void UpdateAABB() { var startPos = Grids.First().PositionComp.GetPosition(); var box = new BoundingBoxD(startPos, startPos); foreach (var aabb in Grids.Select(g => g.PositionComp.WorldAABB)) { box.Include(aabb); } WorldAABB = box; }
public BoundingBoxD GetMechnicalGroupAabb() { BoundingBoxD worldAabb = new BoundingBoxD(); lock (SubLock) { foreach (var sub in ShieldComp.SubGrids) { worldAabb.Include(sub.PositionComp.WorldAABB); } } return(worldAabb); }
public static BoundingBoxD AdjustAABBByVelocity(BoundingBoxD aabb, Vector3 velocity, float inflate = 1.1f) { if (velocity.LengthSquared() > 0.001f) { velocity.Normalize(); } aabb.Inflate((double)inflate); BoundingBoxD box = aabb; box += (BoundingBoxD)((velocity * 2000f) * inflate); aabb.Include(box); return(aabb); }
void UpdateBoundingFrustum() { // Update frustum BoundingFrustum.Matrix = ViewProjectionMatrix; BoundingFrustumFar.Matrix = ViewProjectionMatrixFar; // Update bounding box BoundingBox = BoundingBoxD.CreateInvalid(); BoundingBox.Include(ref BoundingFrustum); // Update bounding sphere BoundingSphere = MyUtils.GetBoundingSphereFromBoundingBox(ref BoundingBox); }
private void PerformJump(Vector3D jumpTarget) { m_jumpDirection = jumpTarget - m_grid.WorldMatrix.Translation; MyParticleEffect effect; if (MyParticlesManager.TryCreateParticleEffect(53, out effect)) { effect.WorldMatrix = MatrixD.CreateFromTransformScale(Quaternion.Identity, m_grid.WorldMatrix.Translation, Vector3D.One); effect.UserScale = (float)m_grid.PositionComp.WorldAABB.HalfExtents.AbsMax() / 25f; effect.AutoDelete = true; } BoundingBoxD aggregateBox = m_grid.PositionComp.WorldAABB; foreach (var grid in m_shipInfo.Keys) { aggregateBox.Include(grid.PositionComp.WorldAABB); } MyPhysics.Clusters.EnsureClusterSpace(aggregateBox + m_jumpDirection); bool updateSpectator = false; if (IsLocalCharacterAffectedByJump()) { updateSpectator = true; } if (updateSpectator) { MyThirdPersonSpectator.Static.ResetPosition(0.0, null); MyThirdPersonSpectator.Static.ResetDistance(); MyThirdPersonSpectator.Static.RecalibrateCameraPosition(); } m_jumped = true; foreach (var grid in m_shipInfo.Keys) { MatrixD gridMatrix = grid.WorldMatrix; gridMatrix.Translation = grid.WorldMatrix.Translation + m_jumpDirection; grid.WorldMatrix = gridMatrix; } if (updateSpectator) { MyThirdPersonSpectator.Static.ResetPosition(0.0, null); MyThirdPersonSpectator.Static.ResetDistance(); MyThirdPersonSpectator.Static.RecalibrateCameraPosition(); } }
public static BoundingBoxD GetWorldAABB(this MyGroups <MyCubeGrid, MyGridPhysicalGroupData> .Group group) { var grids = group.Nodes.Select(n => n.NodeData); var startPos = grids.First().PositionComp.GetPosition(); var box = new BoundingBoxD(startPos, startPos); foreach (var aabb in grids.Select(g => g.PositionComp.WorldAABB)) { box.Include(aabb); } return(box); }
protected void UpdateRenderObject() { m_actualWorldAABB = BoundingBoxD.CreateInvalid(); for (int i = 1; i < Model.Bones.Length; i++) { Vector3D p1 = Vector3D.Transform(Bones[i].Parent.AbsoluteTransform.Translation, WorldMatrix); Vector3D p2 = Vector3D.Transform(Bones[i].AbsoluteTransform.Translation, WorldMatrix); m_actualWorldAABB.Include(ref p1); m_actualWorldAABB.Include(ref p2); } ContainmentType containmentType; m_aabb.Contains(ref m_actualWorldAABB, out containmentType); if (containmentType != ContainmentType.Contains) { m_actualWorldAABB.Inflate(0.5f); MatrixD worldMatrix = WorldMatrix; VRageRender.MyRenderProxy.UpdateRenderObject(Render.RenderObjectIDs[0], ref worldMatrix, false, m_actualWorldAABB); m_aabb = m_actualWorldAABB; } }
private static void CalculateAABB(ref BoundingBoxD bbox, out float scaleZ, out float scaleXY, ref Vector3D position, ref Vector3D direction, ref Vector3D up, float reflectorConeMaxAngleCos, float reflectorRange) { scaleZ = 1; scaleXY = 1; float cosAngle = 1 - reflectorConeMaxAngleCos; scaleZ = reflectorRange; // Calculate cone side (hypotenuse of triangle) float side = reflectorRange / cosAngle; // Calculate cone bottom scale (Pythagoras theorem) scaleXY = (float)System.Math.Sqrt(side * side - reflectorRange * reflectorRange) * 2; if (scaleXY == 0) { scaleXY = 1; } up = MyUtils.Normalize(up); Vector3 coneSideDirection = Vector3.Cross(up, direction); coneSideDirection = MyUtils.Normalize(coneSideDirection); Vector3D coneCenter = position + direction * scaleZ; Vector3D pt1 = coneCenter + coneSideDirection * scaleXY / 2 + up * scaleXY / 2; Vector3D pt2 = coneCenter - coneSideDirection * scaleXY / 2 + up * scaleXY / 2; Vector3D pt3 = coneCenter + coneSideDirection * scaleXY / 2 - up * scaleXY / 2; Vector3D pt4 = coneCenter - coneSideDirection * scaleXY / 2 - up * scaleXY / 2; bbox = BoundingBoxD.CreateInvalid(); bbox = bbox.Include(ref position); //bbox = bbox.Include(ref coneCenter); bbox = bbox.Include(ref pt1); bbox = bbox.Include(ref pt2); bbox = bbox.Include(ref pt3); bbox = bbox.Include(ref pt4); }
public BoundingBoxD GetEntityAABB(AABBEntity entity) { BoundingBoxD bbox = entity.BoundingBox; //Include entity velocity to be able to hit fast moving objects if (entity.WorldTranslation != null && entity.LinearVelocity != null) { bbox = bbox.Include( entity.WorldTranslation + entity.LinearVelocity * MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS * 5 ); } return(bbox); }
public override void UpdateWorldAABB() { CulledObjects.GetAll(m_list, true); m_localAABB = BoundingBoxD.CreateInvalid(); foreach (var element in m_list) { m_localAABB = m_localAABB.Include(element.WorldAABB); } m_aabb = m_localAABB.Transform(ref m_worldMatrix); base.UpdateWorldAABB(); }
public void Init(IMyEnvironmentOwner owner, ref MyEnvironmentSectorParameters parameters) { // Copy parameters in SectorCenter = parameters.Center; Bounds = parameters.Bounds; m_dataRange = parameters.DataRange; m_environment = (MyProceduralEnvironmentDefinition)parameters.Environment; EnvironmentDefinition = parameters.Environment; m_owner = owner; m_provider = parameters.Provider; // Compute appropriate render origin. Vector3D center = parameters.Center; owner.ProjectPointToSurface(ref center); if (!Engine.Platform.Game.IsDedicated) { m_render = new MyInstancedRenderSector(string.Format("{0}:Sector({1:X})", owner, parameters.SectorId), MatrixD.CreateTranslation(center)); } SectorId = parameters.SectorId; BoundingBoxD worldBounds = BoundingBoxD.CreateInvalid(); for (int i = 0; i < 8; ++i) { worldBounds.Include(Bounds[i]); } // Entity stuff PositionComp.SetPosition(parameters.Center); PositionComp.WorldAABB = worldBounds; // Add missing stuff AddDebugRenderComponent(new MyDebugRenderComponentEnvironmentSector(this)); GameLogic = new MyNullGameLogicComponent(); Save = false; IsClosed = false; }
private BoundingBoxD GetAggregateBBox() { if (m_grid.MarkedForClose) { return(BoundingBoxD.CreateInvalid()); } BoundingBoxD bbox = m_grid.PositionComp.WorldAABB; foreach (var grid in m_connectedGrids) { if (grid.PositionComp != null) { bbox.Include(grid.PositionComp.WorldAABB); } } return(bbox); }
private void PerformJump(Vector3D jumpTarget) { m_updateEffectPosition = false; m_jumpDirection = jumpTarget - m_grid.WorldMatrix.Translation; BoundingBoxD aggregateBox = m_grid.PositionComp.WorldAABB; foreach (var grid in m_shipInfo.Keys) { aggregateBox.Include(grid.PositionComp.WorldAABB); } MyPhysics.EnsurePhysicsSpace(aggregateBox + m_jumpDirection); bool updateSpectator = false; if (IsLocalCharacterAffectedByJump()) { updateSpectator = true; } if (updateSpectator) { MyThirdPersonSpectator.Static.ResetViewerAngle(null); MyThirdPersonSpectator.Static.ResetViewerDistance(); MyThirdPersonSpectator.Static.RecalibrateCameraPosition(); } m_jumped = true; foreach (var grid in m_shipInfo.Keys) { MatrixD gridMatrix = grid.WorldMatrix; gridMatrix.Translation = grid.WorldMatrix.Translation + m_jumpDirection; grid.WorldMatrix = gridMatrix; } if (updateSpectator) { MyThirdPersonSpectator.Static.ResetViewerAngle(null); MyThirdPersonSpectator.Static.ResetViewerDistance(); MyThirdPersonSpectator.Static.RecalibrateCameraPosition(); } }
static void SendOutputMessages() { foreach (var q in m_cullQuery.FrustumQueries) { foreach (var proxy in q.List) { // all should have same parent if (proxy.Proxies.Length > 0) { MyRenderProxy.VisibleObjectsWrite.Add(proxy.Proxies[0].Parent.m_owner.ID); } } } // TODO: just for now foreach (var h in MyComponentFactory <MyGroupRootComponent> .GetAll()) { if (true) { BoundingBoxD bb = BoundingBoxD.CreateInvalid(); foreach (var child in h.m_children) { if (child.m_visible) { bb.Include(child.Aabb); } } if (MyEnvironment.ViewFrustumClippedD.Contains(bb) != VRageMath.ContainmentType.Disjoint) { MyRenderProxy.VisibleObjectsWrite.Add(h.m_owner.ID); } } } foreach (var id in MyClipmapFactory.ClipmapByID.Keys) { MyRenderProxy.VisibleObjectsWrite.Add(id); } }
public void MoveObject(ulong id, BoundingBoxD oldAabb, BoundingBoxD aabb, Vector3 velocity) { System.Diagnostics.Debug.Assert(id != CLUSTERED_OBJECT_ID_UNITIALIZED, "Unitialized object in cluster!"); MyObjectData objectData; if (m_objectsData.TryGetValue(id, out objectData)) { System.Diagnostics.Debug.Assert(!objectData.ActivationHandler.IsStaticForCluster, "Cannot move static object!"); var oldAABB = objectData.AABB; m_objectsData[id].AABB = aabb; BoundingBoxD originalAABB = aabb; Vector3 velocityDir = Vector3.Normalize(velocity); BoundingBoxD extendedAABB = aabb.Include(aabb.Center + velocityDir * 2000); // BoundingBoxD newClusterAABB = aabb.Include(aabb.Center + velocityDir * IdealClusterSize / 2); System.Diagnostics.Debug.Assert(m_clusters.Contains(objectData.Cluster)); if (objectData.Cluster.AABB.Contains(extendedAABB) != ContainmentType.Contains && !SingleCluster.HasValue) { ReorderClusters(originalAABB.Include(oldAABB), id); } System.Diagnostics.Debug.Assert(m_objectsData[id].Cluster.AABB.Contains(objectData.AABB) == ContainmentType.Contains || SingleCluster.HasValue, "Inconsistency in clusters"); } //foreach (var ob in m_objectsData) //{ // if (ob.Value.ActivationHandler.IsStatic && ob.Value.Cluster != null) // System.Diagnostics.Debug.Assert(ob.Value.Cluster.AABB.Contains(ob.Value.AABB) != ContainmentType.Disjoint, "Inconsistency in clusters"); // else // if (!ob.Value.ActivationHandler.IsStatic) // System.Diagnostics.Debug.Assert(ob.Value.Cluster.AABB.Contains(ob.Value.AABB) == ContainmentType.Contains, "Inconsistency in clusters"); //} }
public void TestVoxelNavmeshTriangle(ref Vector3D a, ref Vector3D b, ref Vector3D c, List<MyCubeGrid> gridsToTest, List<MyGridPathfinding.CubeId> linkCandidatesOutput, out bool intersecting) { ProfilerShort.Begin("TestVoxelNavmeshTriangle"); ProfilerShort.Begin("Triangle-obstacle tests"); Vector3D s = (a + b + c) / 3.0; if (m_obstacles.IsInObstacle(s)) { intersecting = true; ProfilerShort.End(); ProfilerShort.End(); return; } ProfilerShort.End(); BoundingBoxD triBB; Vector3D aLocal, bLocal, cLocal, gLocal; Vector3D g = Vector3D.Zero; if (MyPerGameSettings.NavmeshPresumesDownwardGravity) { g = Vector3.Down * 2.0f; } m_tmpLinkCandidates.Clear(); intersecting = false; foreach (var grid in gridsToTest) { MatrixD mat = grid.PositionComp.WorldMatrixNormalizedInv; Vector3D.Transform(ref a, ref mat, out aLocal); Vector3D.Transform(ref b, ref mat, out bLocal); Vector3D.Transform(ref c, ref mat, out cLocal); Vector3D.TransformNormal(ref g, ref mat, out gLocal); triBB = new BoundingBoxD(Vector3D.MaxValue, Vector3D.MinValue); triBB.Include(ref aLocal, ref bLocal, ref cLocal); Vector3I min = grid.LocalToGridInteger(triBB.Min); Vector3I max = grid.LocalToGridInteger(triBB.Max); Vector3I pos = min - Vector3I.One; Vector3I max2 = max + Vector3I.One; for (var it = new Vector3I_RangeIterator(ref pos, ref max2); it.IsValid(); it.GetNext(out pos)) { if (grid.GetCubeBlock(pos) != null) { Vector3 largeMin = (pos - Vector3.One) * grid.GridSize; Vector3 largeMax = (pos + Vector3.One) * grid.GridSize; Vector3 smallMin = (pos - Vector3.Half) * grid.GridSize; Vector3 smallMax = (pos + Vector3.Half) * grid.GridSize; BoundingBoxD largeBb = new BoundingBoxD(largeMin, largeMax); BoundingBoxD bb = new BoundingBoxD(smallMin, smallMax); largeBb.Include(largeMin + gLocal); largeBb.Include(largeMax + gLocal); bb.Include(smallMin + gLocal); bb.Include(smallMax + gLocal); ProfilerShort.Begin("Triangle intersection tests"); if (largeBb.IntersectsTriangle(ref aLocal, ref bLocal, ref cLocal)) { if (bb.IntersectsTriangle(ref aLocal, ref bLocal, ref cLocal)) { intersecting = true; ProfilerShort.End(); break; } else { int dx = Math.Min(Math.Abs(min.X - pos.X), Math.Abs(max.X - pos.X)); int dy = Math.Min(Math.Abs(min.Y - pos.Y), Math.Abs(max.Y - pos.Y)); int dz = Math.Min(Math.Abs(min.Z - pos.Z), Math.Abs(max.Z - pos.Z)); if ((dx + dy + dz) < 3) m_tmpLinkCandidates.Add(new MyGridPathfinding.CubeId() { Grid = grid, Coords = pos }); } } ProfilerShort.End(); } } if (intersecting) break; } if (!intersecting) { for (int i = 0; i < m_tmpLinkCandidates.Count; ++i) { linkCandidatesOutput.Add(m_tmpLinkCandidates[i]); } } m_tmpLinkCandidates.Clear(); ProfilerShort.End(); }
/// <summary> /// Adds environment item to internal collections. Creates render and physics data. /// </summary> /// <returns>True if successfully added, otherwise false.</returns> private bool AddItem( MyEnvironmentItemDefinition itemDefinition, ref MatrixD worldMatrix, ref BoundingBoxD aabbWorld, HkStaticCompoundShape sectorRootShape, Dictionary <MyStringHash, HkShape> subtypeIdToShape, int localModelId = MAIN_MODEL_LOCAL_ID) { if (!MyFakes.ENABLE_ENVIRONMENT_ITEMS) { return(true); } Debug.Assert(m_definition.ContainsItemDefinition(itemDefinition), String.Format("Environment item with definition '{0}' not found in class '{1}'", itemDefinition.Id, m_definition.Id)); if (!m_definition.ContainsItemDefinition(itemDefinition)) { return(false); } if (itemDefinition.Model == null) { return(false); } //MyDefinitionId defId = new MyDefinitionId(envItemObjectBuilderType, subtypeId.ToString()); int modelId = MyEnvironmentItems.GetModelId(itemDefinition.Id.SubtypeId, localModelId); string modelName = MyModel.GetById(modelId); MyModel model = MyModels.GetModelOnlyData(modelName); if (model == null) { //Debug.Fail(String.Format("Environment item model of '{0}' not found, skipping the item...", itemDefinition.Id)); return(false); } CheckModelConsistency(itemDefinition); int localId = worldMatrix.Translation.GetHashCode(); MyEnvironmentItemData data = new MyEnvironmentItemData() { Id = localId, SubtypeId = itemDefinition.Id.SubtypeId, Transform = new MyTransformD(ref worldMatrix), Enabled = true, SectorInstanceId = -1, ModelId = modelId, }; //Preload split planes //VRageRender.MyRenderProxy.PreloadMaterials(model.AssetName); aabbWorld.Include(model.BoundingBox.Transform(worldMatrix)); MatrixD transform = data.Transform.TransformMatrix; Vector3I sectorId = MyEnvironmentSector.GetSectorId(transform.Translation - CellsOffset, m_definition.SectorSize); MyEnvironmentSector sector; if (!m_sectors.TryGetValue(sectorId, out sector)) { sector = new MyEnvironmentSector(sectorId, sectorId * m_definition.SectorSize + CellsOffset); m_sectors.Add(sectorId, sector); } // Adds instance of the given model. Local matrix specified might be changed internally in renderer. MatrixD sectorOffset = MatrixD.CreateTranslation(-sectorId * m_definition.SectorSize - CellsOffset); Matrix transformL = (Matrix)(transform * sectorOffset); data.SectorInstanceId = sector.AddInstance(itemDefinition.Id.SubtypeId, data.ModelId, localId, ref transformL, model.BoundingBox, m_instanceFlags, m_definition.MaxViewDistance); int physicsShapeInstanceId; if (AddPhysicsShape(data.SubtypeId, model, ref transform, sectorRootShape, subtypeIdToShape, out physicsShapeInstanceId)) { // Map to data index - note that itemData is added after this to its list! m_physicsShapeInstanceIdToLocalId[physicsShapeInstanceId] = localId; m_localIdToPhysicsShapeInstanceId[localId] = physicsShapeInstanceId; } data.Transform = new MyTransformD(transform); if (m_itemsData.ContainsKey(localId)) { //Debug.Fail("More items on same place! " + transform.Translation.ToString()); } else { m_itemsData.Add(localId, data); } if (ItemAdded != null) { ItemAdded(this, new ItemInfo() { LocalId = localId, SubtypeId = data.SubtypeId, Transform = data.Transform, }); } return(true); }
public void ReorderClusters(BoundingBoxD aabb, ulong objectId = 18446744073709551615L) { using (this.m_clustersReorderLock.AcquireExclusiveUsing()) { aabb.InflateToMinimum(IdealClusterSize); bool flag = false; BoundingBoxD bbox = aabb; this.m_clusterTree.OverlapAllBoundingBox <MyCluster>(ref bbox, m_resultList, 0, true); HashSet <MyObjectData> source = new HashSet <MyObjectData>(); while (!flag) { source.Clear(); if (objectId != ulong.MaxValue) { source.Add(this.m_objectsData[objectId]); } using (List <MyCluster> .Enumerator enumerator = m_resultList.GetEnumerator()) { while (enumerator.MoveNext()) { Func <KeyValuePair <ulong, MyObjectData>, bool> predicate = null; MyCluster collidedCluster = enumerator.Current; bbox.Include(collidedCluster.AABB); if (predicate == null) { predicate = x => collidedCluster.Objects.Contains(x.Key); } foreach (MyObjectData data in from x in this.m_objectsData.Where <KeyValuePair <ulong, MyObjectData> >(predicate) select x.Value) { source.Add(data); } } } int num = m_resultList.Count; this.m_clusterTree.OverlapAllBoundingBox <MyCluster>(ref bbox, m_resultList, 0, true); flag = num == m_resultList.Count; this.m_staticTree.OverlapAllBoundingBox <ulong>(ref bbox, m_objectDataResultList, 0, true); foreach (ulong num2 in m_objectDataResultList) { if ((this.m_objectsData[num2].Cluster != null) && !m_resultList.Contains(this.m_objectsData[num2].Cluster)) { bbox.Include(this.m_objectsData[num2].Cluster.AABB); flag = false; } } } this.m_staticTree.OverlapAllBoundingBox <ulong>(ref bbox, m_objectDataResultList, 0, true); foreach (ulong num3 in m_objectDataResultList) { source.Add(this.m_objectsData[num3]); } Stack <MyClusterDescription> stack = new Stack <MyClusterDescription>(); List <MyClusterDescription> list = new List <MyClusterDescription>(); MyClusterDescription item = new MyClusterDescription { AABB = bbox, DynamicObjects = source.Where <MyObjectData>(delegate(MyObjectData x) { if (x.ActivationHandler != null) { return(!x.ActivationHandler.IsStaticForCluster); } return(true); }).ToList <MyObjectData>(), StaticObjects = (from x in source where (x.ActivationHandler != null) && x.ActivationHandler.IsStaticForCluster select x).ToList <MyObjectData>() }; stack.Push(item); List <MyObjectData> list2 = (from x in item.StaticObjects where x.Cluster != null select x).ToList <MyObjectData>(); int count = item.StaticObjects.Count; while (stack.Count > 0) { MyClusterDescription description2 = stack.Pop(); if (description2.DynamicObjects.Count != 0) { BoundingBoxD xd2 = BoundingBoxD.CreateInvalid(); for (int i = 0; i < description2.DynamicObjects.Count; i++) { MyObjectData data2 = description2.DynamicObjects[i]; BoundingBoxD inflated = data2.AABB.GetInflated((Vector3)(IdealClusterSize / 2f)); xd2.Include(inflated); } BoundingBoxD xd4 = xd2; Vector3D max = xd2.Max; int num5 = xd2.Size.AbsMaxComponent(); switch (num5) { case 0: description2.DynamicObjects.Sort(AABBComparerX.Static); break; case 1: description2.DynamicObjects.Sort(AABBComparerY.Static); break; case 2: description2.DynamicObjects.Sort(AABBComparerZ.Static); break; } bool flag2 = false; if (xd2.Size.AbsMax() >= MaximumForSplit.AbsMax()) { for (int j = 1; j < description2.DynamicObjects.Count; j++) { MyObjectData data3 = description2.DynamicObjects[j - 1]; MyObjectData data4 = description2.DynamicObjects[j]; BoundingBoxD xd5 = data3.AABB.GetInflated((Vector3)(IdealClusterSize / 2f)); if ((data4.AABB.GetInflated((Vector3)(IdealClusterSize / 2f)).Min.GetDim(num5) - xd5.Max.GetDim(num5)) > 0.0) { flag2 = true; max.SetDim(num5, xd5.Max.GetDim(num5)); break; } } } xd4.Max = max; xd4.InflateToMinimum(IdealClusterSize); MyClusterDescription description3 = new MyClusterDescription { AABB = xd4, DynamicObjects = new List <MyObjectData>(), StaticObjects = new List <MyObjectData>() }; foreach (MyObjectData data5 in description2.DynamicObjects.ToList <MyObjectData>()) { if (xd4.Contains(data5.AABB) == ContainmentType.Contains) { description3.DynamicObjects.Add(data5); description2.DynamicObjects.Remove(data5); } } foreach (MyObjectData data6 in description2.StaticObjects.ToList <MyObjectData>()) { switch (xd4.Contains(data6.AABB)) { case ContainmentType.Contains: case ContainmentType.Intersects: description3.StaticObjects.Add(data6); description2.StaticObjects.Remove(data6); break; } } description3.AABB = xd4; if (description2.DynamicObjects.Count > 0) { BoundingBoxD xd7 = BoundingBoxD.CreateInvalid(); foreach (MyObjectData data7 in description2.DynamicObjects) { xd7.Include(data7.AABB.GetInflated(MinimumDistanceFromBorder)); } xd7.InflateToMinimum(IdealClusterSize); MyClusterDescription description4 = new MyClusterDescription { AABB = xd7, DynamicObjects = description2.DynamicObjects.ToList <MyObjectData>(), StaticObjects = description2.StaticObjects.ToList <MyObjectData>() }; if (description4.AABB.Size.AbsMax() > (2f * IdealClusterSize.AbsMax())) { stack.Push(description4); } else { list.Add(description4); } } if ((description3.AABB.Size.AbsMax() > (2f * IdealClusterSize.AbsMax())) && flag2) { stack.Push(description3); } else { list.Add(description3); } } } HashSet <MyCluster> set2 = new HashSet <MyCluster>(); HashSet <MyCluster> set3 = new HashSet <MyCluster>(); foreach (MyObjectData data8 in list2) { if (data8.Cluster != null) { set2.Add(data8.Cluster); this.RemoveObjectFromCluster(data8, true); } } foreach (MyObjectData data9 in list2) { if (data9.Cluster != null) { data9.ActivationHandler.FinishRemoveBatch(data9.Cluster.UserData); data9.Cluster = null; } } int num7 = 0; foreach (MyClusterDescription description7 in list) { BoundingBoxD aABB = description7.AABB; MyCluster cluster = this.CreateCluster(ref aABB); foreach (MyObjectData data10 in description7.DynamicObjects) { if (data10.Cluster != null) { set2.Add(data10.Cluster); this.RemoveObjectFromCluster(data10, true); } } foreach (MyObjectData data11 in description7.DynamicObjects) { if (data11.Cluster != null) { data11.ActivationHandler.FinishRemoveBatch(data11.Cluster.UserData); data11.Cluster = null; } } foreach (MyCluster cluster2 in set2) { if (this.OnFinishBatch != null) { this.OnFinishBatch(cluster2.UserData); } } foreach (MyObjectData data12 in description7.DynamicObjects) { this.AddObjectToCluster(cluster, data12.Id, true); } foreach (MyObjectData data13 in description7.StaticObjects) { if (cluster.AABB.Contains(data13.AABB) != ContainmentType.Disjoint) { this.AddObjectToCluster(cluster, data13.Id, true); num7++; } } set3.Add(cluster); } foreach (MyCluster cluster3 in set2) { this.RemoveCluster(cluster3); } foreach (MyCluster cluster4 in set3) { if (this.OnFinishBatch != null) { this.OnFinishBatch(cluster4.UserData); } foreach (ulong num8 in cluster4.Objects) { if (this.m_objectsData[num8].ActivationHandler != null) { this.m_objectsData[num8].ActivationHandler.FinishAddBatch(); } } } if (this.OnClustersReordered != null) { this.OnClustersReordered(); } } }
void DrawBlockSelection(IMySlimBlock block, SelectionState state, bool primarySelection = false) { IMyCubeGrid grid = block.CubeGrid; MyCubeBlockDefinition def = (MyCubeBlockDefinition)block.BlockDefinition; Color color = (state == SelectionState.InvalidButMirrorValid ? Color.Yellow : (state == SelectionState.Valid ? Color.Green : Color.Red)); MatrixD worldMatrix; BoundingBoxD localBB; #region Compute box MyCubeBlock fatBlock = block.FatBlock as MyCubeBlock; if (fatBlock != null) { worldMatrix = fatBlock.PositionComp.WorldMatrixRef; if (Main.Tick % (Constants.TICKS_PER_SECOND / 4) == 0 || !LocalBBCache.TryGetValue(block, out localBB)) { BoundingBox localAABB = fatBlock.PositionComp.LocalAABB; localBB = new BoundingBoxD(localAABB.Min, localAABB.Max); #region Subpart localBB inclusion if (fatBlock.Subparts != null) { MatrixD transformToBlockLocal = fatBlock.PositionComp.WorldMatrixInvScaled; foreach (VRage.Game.Entity.MyEntitySubpart s1 in fatBlock.Subparts.Values) { MyOrientedBoundingBoxD obbS1 = new MyOrientedBoundingBoxD(s1.PositionComp.LocalAABB, s1.PositionComp.WorldMatrixRef); obbS1.GetCorners(Corners, 0); for (int i = 0; i < Corners.Length; i++) { Vector3D corner = Corners[i]; localBB.Include(Vector3D.Transform(corner, transformToBlockLocal)); } if (s1.Subparts != null) { foreach (VRage.Game.Entity.MyEntitySubpart s2 in s1.Subparts.Values) { MyOrientedBoundingBoxD obbS2 = new MyOrientedBoundingBoxD(s2.PositionComp.LocalAABB, s2.PositionComp.WorldMatrixRef); obbS2.GetCorners(Corners, 0); for (int i = 0; i < Corners.Length; i++) { Vector3D corner = Corners[i]; localBB.Include(Vector3D.Transform(corner, transformToBlockLocal)); } if (s2.Subparts != null) { foreach (VRage.Game.Entity.MyEntitySubpart s3 in s2.Subparts.Values) { MyOrientedBoundingBoxD obbS3 = new MyOrientedBoundingBoxD(s3.PositionComp.LocalAABB, s3.PositionComp.WorldMatrixRef); obbS3.GetCorners(Corners, 0); for (int i = 0; i < Corners.Length; i++) { Vector3D corner = Corners[i]; localBB.Include(Vector3D.Transform(corner, transformToBlockLocal)); } if (s3.Subparts != null) { foreach (VRage.Game.Entity.MyEntitySubpart s4 in s3.Subparts.Values) { MyOrientedBoundingBoxD obbS4 = new MyOrientedBoundingBoxD(s4.PositionComp.LocalAABB, s4.PositionComp.WorldMatrixRef); obbS4.GetCorners(Corners, 0); for (int i = 0; i < Corners.Length; i++) { Vector3D corner = Corners[i]; localBB.Include(Vector3D.Transform(corner, transformToBlockLocal)); } } } } } } } } } #endregion LocalBBCache[block] = localBB; } } else { Matrix localMatrix; block.Orientation.GetMatrix(out localMatrix); localMatrix.Translation = new Vector3(block.Position) * grid.GridSize; worldMatrix = localMatrix * grid.WorldMatrix; Vector3 halfSize = def.Size * (grid.GridSize * 0.5f); localBB = new BoundingBoxD(-halfSize, halfSize); } #endregion localBB.Inflate((grid.GridSizeEnum == MyCubeSize.Large ? 0.1 : 0.03)); float lineWidth; if (primarySelection) { lineWidth = (grid.GridSizeEnum == MyCubeSize.Large ? 0.02f : 0.016f); } else { lineWidth = (grid.GridSizeEnum == MyCubeSize.Large ? 0.25f : 0.1f); // thicker mirrored selections to see better in distance } DrawSelectionLines(ref worldMatrix, ref localBB, color, lineWidth); }
public void MoveObject(ulong id, BoundingBoxD oldAabb, BoundingBoxD aabb, Vector3 velocity) { System.Diagnostics.Debug.Assert(id != CLUSTERED_OBJECT_ID_UNITIALIZED, "Unitialized object in cluster!"); MyObjectData objectData; if (m_objectsData.TryGetValue(id, out objectData)) { System.Diagnostics.Debug.Assert(!objectData.ActivationHandler.IsStaticForCluster, "Cannot move static object!"); var oldAABB = objectData.AABB; m_objectsData[id].AABB = aabb; BoundingBoxD originalAABB = aabb; Vector3 velocityDir = velocity; if (velocity.LengthSquared() > 0.001f) { velocityDir = Vector3.Normalize(velocity); } BoundingBoxD extendedAABB = aabb.Include(aabb.Center + velocityDir * 2000); // BoundingBoxD newClusterAABB = aabb.Include(aabb.Center + velocityDir * IdealClusterSize / 2); originalAABB.InflateToMinimum(IdealClusterSize); System.Diagnostics.Debug.Assert(m_clusters.Contains(objectData.Cluster)); var newContainmentType = objectData.Cluster.AABB.Contains(extendedAABB); if (newContainmentType != ContainmentType.Contains && !SingleCluster.HasValue) { if (newContainmentType == ContainmentType.Disjoint) { //Probably caused by teleport m_clusterTree.OverlapAllBoundingBox(ref extendedAABB, m_returnedClusters); if ((m_returnedClusters.Count == 1) && (m_returnedClusters[0].AABB.Contains(extendedAABB) == ContainmentType.Contains)) { //Just move object from one cluster to another var oldCluster = objectData.Cluster; RemoveObjectFromCluster(objectData, false); if (oldCluster.Objects.Count == 0) { RemoveCluster(oldCluster); } AddObjectToCluster(m_returnedClusters[0], objectData.Id, false); } else { ReorderClusters(originalAABB.Include(oldAABB), id); } } else { ReorderClusters(originalAABB.Include(oldAABB), id); } } System.Diagnostics.Debug.Assert(m_objectsData[id].Cluster.AABB.Contains(objectData.AABB) == ContainmentType.Contains || SingleCluster.HasValue, "Inconsistency in clusters"); } //foreach (var ob in m_objectsData) //{ // if (ob.Value.ActivationHandler.IsStatic && ob.Value.Cluster != null) // System.Diagnostics.Debug.Assert(ob.Value.Cluster.AABB.Contains(ob.Value.AABB) != ContainmentType.Disjoint, "Inconsistency in clusters"); // else // if (!ob.Value.ActivationHandler.IsStatic) // System.Diagnostics.Debug.Assert(ob.Value.Cluster.AABB.Contains(ob.Value.AABB) == ContainmentType.Contains, "Inconsistency in clusters"); //} }
public bool Update() { if (!Enabled) { return(AutoDelete); //efect is not enabled at all and must be deleted } System.Diagnostics.Debug.Assert(WorldMatrix != MatrixD.Zero, "Effect world matrix was not set!"); if (!m_isPreloading && !m_wasPreloaded && m_preload > 0) { m_isPreloading = true; // TODO: Optimize (preload causes lags, depending on preload size, it's from 0 ms to 85 ms) while (m_elapsedTime < m_preload) { Update(); } m_isPreloading = false; m_wasPreloaded = true; } VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("ParticleEffect-Update"); if (!m_isPreloading && IsInFrustum) { MyPerformanceCounter.PerCameraDrawWrite.ParticleEffectsDrawn++; } VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock(); VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("ParticleEffect-UpdateGen"); m_elapsedTime += MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS; //m_distance = MySector.MainCamera.GetDistanceWithFOV(WorldMatrix.Translation) / (100.0f); //precalculate for LODs m_distance = (float)Vector3D.Distance(MyTransparentGeometry.Camera.Translation, WorldMatrix.Translation) / (100.0f); //precalculate for LODs m_particlesCount = 0; m_birthRate = 0; m_AABB = BoundingBoxD.CreateInvalid(); //if (CalculateDeltaMatrix) //{ //DeltaMatrix = Matrix.Invert(m_lastWorldMatrix) * m_worldMatrix; //} if (Velocity != Vector3.Zero) { var position = m_worldMatrix.Translation; position.X += Velocity.X * MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS; position.Y += Velocity.Y * MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS; position.Z += Velocity.Z * MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS; m_worldMatrix = MatrixD.CreateWorld(position, Vector3D.Normalize(Velocity), m_worldMatrix.Up); } //if (RenderCounter == 0 || ((MyRender.RenderCounter - RenderCounter) < FRAMES_TO_SKIP)) //more than FRAMES_TO_SKIP frames consider effect as invisible { foreach (MyParticleGeneration generation in m_generations) { generation.EffectMatrix = WorldMatrix; generation.Update(); m_particlesCount += generation.GetParticlesCount(); m_birthRate += generation.GetBirthRate(); BoundingBoxD bbox = generation.GetAABB(); m_AABB = m_AABB.Include(ref bbox); } if (m_particlesCount > 0) { m_hasShownSomething = true; } //TODO IsInFrustum = true; // MySector.MainCamera.IsInFrustum(ref m_AABB); } VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock(); m_lastWorldMatrix = m_worldMatrix; if (((m_particlesCount == 0 && HasShownSomething()) || (m_particlesCount == 0 && m_birthRate == 0.0f)) && AutoDelete && !m_isPreloading) { //Effect was played and has to be deleted return(true); } if (!m_isPreloading && OnUpdate != null) { OnUpdate(this, null); } return(false); }
public bool Update() { if (!Enabled) return AutoDelete; //efect is not enabled at all and must be deleted if (WorldMatrix == MatrixD.Zero) return true; System.Diagnostics.Debug.Assert(WorldMatrix != MatrixD.Zero, "Effect world matrix was not set!"); if (!m_isPreloading && !m_wasPreloaded && m_preload > 0) { m_isPreloading = true; // TODO: Optimize (preload causes lags, depending on preload size, it's from 0 ms to 85 ms) while (m_elapsedTime < m_preload) { Update(); } m_isPreloading = false; m_wasPreloaded = true; } if (MyParticlesManager.CalculateGravityInPoint != null && m_updateCounter == 0) Gravity = MyParticlesManager.CalculateGravityInPoint(WorldMatrix.Translation); m_updateCounter++; if (m_updateCounter > GRAVITY_UPDATE_DELAY) { m_updateCounter = 0; } VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("ParticleEffect-Update"); if (!m_isPreloading) { MyPerformanceCounter.PerCameraDrawWrite.ParticleEffectsDrawn++; } VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock(); VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("ParticleEffect-UpdateGen"); m_elapsedTime += VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS; //m_distance = MySector.MainCamera.GetDistanceWithFOV(WorldMatrix.Translation) / (100.0f); //precalculate for LODs m_distance = (float)Vector3D.Distance(MyTransparentGeometry.Camera.Translation, WorldMatrix.Translation) / (100.0f); //precalculate for LODs m_particlesCount = 0; m_birthRate = 0; m_AABB = BoundingBoxD.CreateInvalid(); if (Velocity != Vector3.Zero) { var position = m_worldMatrix.Translation; position.X += Velocity.X * VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS; position.Y += Velocity.Y * VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS; position.Z += Velocity.Z * VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS; m_worldMatrix = MatrixD.CreateWorld(position, Vector3D.Normalize(Velocity), m_worldMatrix.Up); } foreach (MyParticleGeneration generation in m_generations) { generation.EffectMatrix = WorldMatrix; generation.Update(); m_particlesCount += generation.GetParticlesCount(); m_birthRate += generation.GetBirthRate(); BoundingBoxD bbox = generation.GetAABB(); m_AABB = m_AABB.Include(ref bbox); } if (m_particlesCount > 0) m_hasShownSomething = true; foreach (var particleLight in m_particleLights) { particleLight.Update(); } VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock(); m_lastWorldMatrix = m_worldMatrix; if (((m_particlesCount == 0 && HasShownSomething()) || (m_particlesCount == 0 && m_birthRate == 0.0f)) && AutoDelete && !m_isPreloading) { //Effect was played and has to be deleted return true; } if (!m_isPreloading && OnUpdate != null) OnUpdate(this, null); return false; }
private void CreateParticle(Vector3D interpolatedEffectPosition) { MyAnimatedParticle particle = MyTransparentGeometry.AddAnimatedParticle(); if (particle == null) { return; } particle.Type = (MyParticleTypeEnum)ParticleType.GetValue <int>(); MyUtils.AssertIsValid(m_effect.WorldMatrix); Vector3D startOffset; m_emitter.CalculateStartPosition(m_effect.GetElapsedTime(), MatrixD.CreateWorld(interpolatedEffectPosition, m_effect.WorldMatrix.Forward, m_effect.WorldMatrix.Up), m_effect.UserEmitterScale * m_effect.UserScale, out startOffset, out particle.StartPosition); Vector3D particlePosition = particle.StartPosition; m_AABB = m_AABB.Include(ref particlePosition); Life.GetInterpolatedValue <float>(m_effect.GetElapsedTime(), out particle.Life); float lifeVar = LifeVar; if (lifeVar > 0) { particle.Life = MathHelper.Max(MyUtils.GetRandomFloat(particle.Life - lifeVar, particle.Life + lifeVar), 0.1f); } Vector3 vel; Velocity.GetInterpolatedValue <Vector3>(m_effect.GetElapsedTime(), out vel); vel.X *= m_effect.UserScale; vel.Y *= m_effect.UserScale; vel.Z *= m_effect.UserScale; particle.Velocity = vel; if (VelocityDir == MyVelocityDirEnum.FromEmitterCenter) { if (!MyUtils.IsZero(startOffset - particle.StartPosition)) { float length = particle.Velocity.Length(); particle.Velocity = MyUtils.Normalize(particle.StartPosition - (Vector3D)startOffset) * length; } } particle.Velocity = Vector3D.TransformNormal(particle.Velocity, GetEffect().WorldMatrix); Angle.GetInterpolatedValue <float>(m_effect.GetElapsedTime(), out particle.Angle); float angleVar = AngleVar; if (angleVar > 0) { particle.Angle = MyUtils.GetRandomFloat(particle.Angle - AngleVar, particle.Angle + AngleVar); } RotationSpeed.GetInterpolatedValue <float>(m_effect.GetElapsedTime(), out particle.RotationSpeed); float rotationSpeedVar = RotationSpeedVar; if (rotationSpeedVar > 0) { particle.RotationSpeed = MyUtils.GetRandomFloat(particle.RotationSpeed - RotationSpeedVar, particle.RotationSpeed + RotationSpeedVar); } float radiusVar; RadiusVar.GetInterpolatedValue <float>(m_effect.GetElapsedTime(), out radiusVar); float lodRadius = 1.0f; if (GetEffect().EnableLods) { LODRadius.GetInterpolatedValue <float>(GetEffect().Distance, out lodRadius); } Radius.GetInterpolatedKeys(m_effect.GetElapsedTime(), radiusVar, (EnableCustomRadius.GetValue <bool>() ? m_effect.UserRadiusMultiplier : 1.0f) * lodRadius * GetEffect().UserScale, particle.Radius); if (particle.Type != MyParticleTypeEnum.Point) { Thickness.GetInterpolatedValue <float>(m_effect.GetElapsedTime(), out particle.Thickness); } particle.Thickness *= lodRadius; float colorVar; ColorVar.GetInterpolatedValue <float>(m_effect.GetElapsedTime(), out colorVar); Color.GetInterpolatedKeys(m_effect.GetElapsedTime(), colorVar, 1.0f, particle.Color); Material.GetInterpolatedKeys(m_effect.GetElapsedTime(), 0, 1.0f, particle.Material); particle.Flags = 0; particle.Flags |= BlendTextures.GetValue <bool>() ? MyAnimatedParticle.ParticleFlags.BlendTextures : 0; particle.Flags |= GetEffect().IsInFrustum ? MyAnimatedParticle.ParticleFlags.IsInFrustum : 0; particle.Start(this); m_particles.Add(particle); }
private void CalcBox() { m_boundingBox = new BoundingBoxD(); m_boundingBox.Include(m_line.From); m_boundingBox.Include(m_line.To); m_calculatedBox = true; }
public bool Intersects(ref BoundingSphereD localSphere) { MyPrecalcComponent.AssertUpdateThread(); // Get min and max cell coordinate where boundingBox can fit BoundingBoxD sphereBoundingBox = BoundingBoxD.CreateInvalid(); sphereBoundingBox.Include(ref localSphere); Vector3I cellCoordMin, cellCoordMax; { Vector3D minD = sphereBoundingBox.Min; Vector3D maxD = sphereBoundingBox.Max; MyVoxelCoordSystems.LocalPositionToGeometryCellCoord(ref minD, out cellCoordMin); MyVoxelCoordSystems.LocalPositionToGeometryCellCoord(ref maxD, out cellCoordMax); } // Fix min and max cell coordinates so they don't overlap the voxelmap ClampCellCoord(ref cellCoordMin); ClampCellCoord(ref cellCoordMax); MyCellCoord cell = new MyCellCoord(); for (cell.CoordInLod.X = cellCoordMin.X; cell.CoordInLod.X <= cellCoordMax.X; cell.CoordInLod.X++) { for (cell.CoordInLod.Y = cellCoordMin.Y; cell.CoordInLod.Y <= cellCoordMax.Y; cell.CoordInLod.Y++) { for (cell.CoordInLod.Z = cellCoordMin.Z; cell.CoordInLod.Z <= cellCoordMax.Z; cell.CoordInLod.Z++) { // If no overlap between bounding box of data cell and the sphere BoundingBox cellBoundingBox; MyVoxelCoordSystems.GeometryCellCoordToLocalAABB(ref cell.CoordInLod, out cellBoundingBox); if (cellBoundingBox.Intersects(ref localSphere) == false) { continue; } // Get cell from cache. If not there, precalc it and store in the cache. // If null is returned, we know that cell doesn't contain any triangleVertexes so we don't need to do intersections. CellData cachedData = GetCell(ref cell); if (cachedData == null) { continue; } for (int i = 0; i < cachedData.VoxelTrianglesCount; i++) { MyVoxelTriangle voxelTriangle = cachedData.VoxelTriangles[i]; MyTriangle_Vertexes triangle; cachedData.GetUnpackedPosition(voxelTriangle.VertexIndex0, out triangle.Vertex0); cachedData.GetUnpackedPosition(voxelTriangle.VertexIndex1, out triangle.Vertex1); cachedData.GetUnpackedPosition(voxelTriangle.VertexIndex2, out triangle.Vertex2); BoundingBox localTriangleAABB = BoundingBox.CreateInvalid(); localTriangleAABB.Include(ref triangle.Vertex0); localTriangleAABB.Include(ref triangle.Vertex1); localTriangleAABB.Include(ref triangle.Vertex2); // First test intersection of triangle's bounding box with line's bounding box. And only if they overlap or intersect, do further intersection tests. if (localTriangleAABB.Intersects(ref localSphere)) { PlaneD trianglePlane = new PlaneD(triangle.Vertex0, triangle.Vertex1, triangle.Vertex2); if (MyUtils.GetSphereTriangleIntersection(ref localSphere, ref trianglePlane, ref triangle) != null) { // If intersection found - we are finished. We don't need to look for more. return(true); } } } } } } return(false); }
/// <summary> /// Adds environment item to internal collections. Creates render and physics data. /// </summary> /// <returns>True if successfully added, otherwise false.</returns> private bool AddItem( MyEnvironmentItemDefinition itemDefinition, ref MatrixD worldMatrix, ref BoundingBoxD aabbWorld, HkStaticCompoundShape sectorRootShape, Dictionary<MyStringHash, HkShape> subtypeIdToShape, int localModelId = MAIN_MODEL_LOCAL_ID) { if (!MyFakes.ENABLE_ENVIRONMENT_ITEMS) return true; Debug.Assert(m_definition.ContainsItemDefinition(itemDefinition), String.Format("Environment item with definition '{0}' not found in class '{1}'", itemDefinition.Id, m_definition.Id)); if (!m_definition.ContainsItemDefinition(itemDefinition)) { return false; } if (itemDefinition.Model == null) return false; //MyDefinitionId defId = new MyDefinitionId(envItemObjectBuilderType, subtypeId.ToString()); int modelId = MyEnvironmentItems.GetModelId(itemDefinition.Id.SubtypeId, localModelId); string modelName = MyModel.GetById(modelId); MyModel model = MyModels.GetModelOnlyData(modelName); if (model == null) { //Debug.Fail(String.Format("Environment item model of '{0}' not found, skipping the item...", itemDefinition.Id)); return false; } CheckModelConsistency(itemDefinition); int localId = worldMatrix.Translation.GetHashCode(); MyEnvironmentItemData data = new MyEnvironmentItemData() { Id = localId, SubtypeId = itemDefinition.Id.SubtypeId, Transform = new MyTransformD(ref worldMatrix), Enabled = true, SectorInstanceId = -1, ModelId = modelId, }; //Preload split planes //VRageRender.MyRenderProxy.PreloadMaterials(model.AssetName); aabbWorld.Include(model.BoundingBox.Transform(worldMatrix)); MatrixD transform = data.Transform.TransformMatrix; Vector3I sectorId = MyEnvironmentSector.GetSectorId(transform.Translation - CellsOffset, m_definition.SectorSize); MyEnvironmentSector sector; if (!m_sectors.TryGetValue(sectorId, out sector)) { sector = new MyEnvironmentSector(sectorId, sectorId * m_definition.SectorSize + CellsOffset); m_sectors.Add(sectorId, sector); } // Adds instance of the given model. Local matrix specified might be changed internally in renderer. MatrixD sectorOffset = MatrixD.CreateTranslation(-sectorId * m_definition.SectorSize - CellsOffset); Matrix transformL = (Matrix)(transform * sectorOffset); data.SectorInstanceId = sector.AddInstance(itemDefinition.Id.SubtypeId, data.ModelId, localId, ref transformL, model.BoundingBox, m_instanceFlags, m_definition.MaxViewDistance); int physicsShapeInstanceId; if (AddPhysicsShape(data.SubtypeId, model, ref transform, sectorRootShape, subtypeIdToShape, out physicsShapeInstanceId)) { // Map to data index - note that itemData is added after this to its list! m_physicsShapeInstanceIdToLocalId[physicsShapeInstanceId] = localId; m_localIdToPhysicsShapeInstanceId[localId] = physicsShapeInstanceId; } data.Transform = new MyTransformD(transform); if (m_itemsData.ContainsKey(localId)) { //Debug.Fail("More items on same place! " + transform.Translation.ToString()); } else { m_itemsData.Add(localId, data); } if (ItemAdded != null) { ItemAdded(this, new ItemInfo() { LocalId = localId, SubtypeId = data.SubtypeId, Transform = data.Transform, }); } return true; }
public static void DebugDrawClusters() { if (Clusters == null) { return; } double previewScale = 2000; MatrixD previewMatrix = MatrixD.CreateWorld(DebugDrawClustersMatrix.Translation + previewScale * DebugDrawClustersMatrix.Forward, Vector3D.Forward, Vector3D.Up); m_resultWorlds.Clear(); Clusters.GetAll(m_resultWorlds); BoundingBoxD totalBox = BoundingBoxD.CreateInvalid(); foreach (var res in m_resultWorlds) { totalBox = totalBox.Include(res.AABB); } double maxAxis = totalBox.Size.AbsMax(); //double scaleAxis = 0.057142857142857141; double scaleAxis = previewScale / maxAxis; //Vector3D scale = new Vector3D(totalBox.Size.X * scaleAxis, totalBox.Size.Y * scaleAxis, totalBox.Size.Z * scaleAxis); Vector3D center = totalBox.Center; totalBox.Min -= center; totalBox.Max -= center; { BoundingBoxD scaledBox = new BoundingBoxD(totalBox.Min * scaleAxis * 1.02f, totalBox.Max * scaleAxis * 1.02f); MyOrientedBoundingBoxD oriented = new MyOrientedBoundingBoxD(scaledBox, previewMatrix); MyRenderProxy.DebugDrawOBB(oriented, Vector3.Up, 1, false, false); MyRenderProxy.DebugDrawAxis(previewMatrix, 50, false); if (MySession.Static != null) { foreach (var player in Sandbox.Game.Multiplayer.Sync.Players.GetOnlinePlayers()) { if (player.Character != null) { var playerPos = Vector3D.Transform((player.Character.PositionComp.GetPosition() - center) * scaleAxis, previewMatrix); MyRenderProxy.DebugDrawSphere(playerPos, 10, Vector3.One, 1, false); } } } } Clusters.GetAllStaticObjects(m_clusterStaticObjects); foreach (var staticBB in m_clusterStaticObjects) { BoundingBoxD scaledBox = new BoundingBoxD((staticBB.Min - center) * scaleAxis, (staticBB.Max - center) * scaleAxis); MyOrientedBoundingBoxD oriented = new MyOrientedBoundingBoxD(scaledBox, previewMatrix); MyRenderProxy.DebugDrawOBB(oriented, Color.Blue, 1, false, false); } foreach (var res in m_resultWorlds) { BoundingBoxD scaledBox = new BoundingBoxD((res.AABB.Min - center) * scaleAxis, (res.AABB.Max - center) * scaleAxis); MyOrientedBoundingBoxD oriented = new MyOrientedBoundingBoxD(scaledBox, previewMatrix); MyRenderProxy.DebugDrawOBB(oriented, Vector3.One, 1, false, false); foreach (var rb in ((HkWorld)res.UserData).CharacterRigidBodies) { Vector3D rbCenter = res.AABB.Center + rb.Position; rbCenter = (rbCenter - center) * scaleAxis; rbCenter = Vector3D.Transform(rbCenter, previewMatrix); Vector3D velocity = rb.LinearVelocity; velocity = Vector3D.TransformNormal(velocity, previewMatrix) * 10; MyRenderProxy.DebugDrawLine3D(rbCenter, rbCenter + velocity, Color.Blue, Color.White, false); } foreach (var rb in ((HkWorld)res.UserData).RigidBodies) { MyOrientedBoundingBoxD rbbb = new MyOrientedBoundingBoxD((BoundingBoxD)rb.GetEntity().LocalAABB, rb.GetEntity().WorldMatrix); rbbb.Center = (rbbb.Center - center) * scaleAxis; rbbb.HalfExtent *= scaleAxis; rbbb.Transform(previewMatrix); MyRenderProxy.DebugDrawOBB(rbbb, Color.Yellow, 1, false, false); //BoundingBoxD rbaa = rb.GetEntity().WorldAABB; //rbaa.Min = (rbaa.Min - center) * scaleAxis; //rbaa.Max = (rbaa.Max - center) * scaleAxis; //MyRenderProxy.DebugDrawAABB(rbaa, new Vector3(0.8f, 0.8f, 0.8f), 1, 1, false); Vector3D velocity = rb.LinearVelocity; velocity = Vector3D.TransformNormal(velocity, previewMatrix) * 10; MyRenderProxy.DebugDrawLine3D(rbbb.Center, rbbb.Center + velocity, Color.Red, Color.White, false); if (velocity.Length() > 1) { BoundingBoxD ideal = new BoundingBoxD(rb.GetEntity().WorldAABB.Center - MyHavokCluster.IdealClusterSize / 2, rb.GetEntity().WorldAABB.Center + MyHavokCluster.IdealClusterSize / 2); MyOrientedBoundingBoxD idealObb = new MyOrientedBoundingBoxD(ideal, MatrixD.Identity); idealObb.Center = (ideal.Center - center) * scaleAxis; idealObb.HalfExtent *= scaleAxis; idealObb.Transform(previewMatrix); MyRenderProxy.DebugDrawOBB(idealObb, new Vector3(0, 0, 1), 1, false, false); } } } }
public override IMyReplicable GetDependency() { if (m_physicsSync == null || Grid.IsStatic) { return(null); } MyCubeGrid master = MyGridPhysicsStateGroup.GetMasterGrid(Grid); if (master != Grid) { return(MyExternalReplicable.FindByObject(master)); } BoundingBoxD box = Grid.PositionComp.WorldAABB; var group = MyCubeGridGroups.Static.PhysicalDynamic.GetGroup(Grid); if (group != null) { foreach (var node in group.Nodes) { box.Include(node.NodeData.PositionComp.WorldAABB); } } if (m_foundEntities == null) { m_foundEntities = new List <MyEntity>(); } m_foundEntities.Clear(); MyGamePruningStructure.GetTopMostEntitiesInBox(ref box, m_foundEntities); float maxRadius = 0; MyCubeGrid biggestGrid = null; foreach (var entity in m_foundEntities) { MyCubeGrid grid = entity as MyCubeGrid; if (grid != null) { // Dont check for projections if (grid.Projector != null) { continue; } var rad = grid.PositionComp.LocalVolume.Radius; if (rad > maxRadius || (rad == maxRadius && (biggestGrid == null || grid.EntityId > biggestGrid.EntityId))) { maxRadius = rad; biggestGrid = grid; } } } if (biggestGrid != null && biggestGrid != Grid) { return(MyExternalReplicable.FindByObject(biggestGrid)); } return(null); }
private static void GetSafeBoundingBoxForPlayers(Vector3D start, double spawnDistance, out BoundingBoxD output) { double tolerance = 10.0f; BoundingSphereD sphere = new BoundingSphereD(start, tolerance); var players = MySession.Static.Players.GetOnlinePlayers(); bool tryIncludeOtherPlayers = true; // We have to try adding other players until the bounding sphere stays the same while (tryIncludeOtherPlayers) { tryIncludeOtherPlayers = false; foreach (var player in players) { Vector3D playerPosition = player.GetPosition(); double distanceFromSphere = (sphere.Center - playerPosition).Length() - sphere.Radius; if (distanceFromSphere <= 0.0) continue; if (distanceFromSphere > spawnDistance * 2.0f) continue; sphere.Include(new BoundingSphereD(playerPosition, tolerance)); tryIncludeOtherPlayers = true; } } sphere.Radius += spawnDistance; output = new BoundingBoxD(sphere.Center - new Vector3D(sphere.Radius), sphere.Center + new Vector3D(sphere.Radius)); var entities = MyEntities.GetEntitiesInAABB(ref output); foreach (var entity in entities) { if (entity is MyCubeGrid) { var cubeGrid = entity as MyCubeGrid; if (cubeGrid.IsStatic) { Vector3D gridPosition = cubeGrid.PositionComp.GetPosition(); // If grid is close to picked player we need to include it's "safe" bounding box for spawning ships, // so cargo ships don't spawn near it. output.Include(new BoundingBoxD(new Vector3D(gridPosition - spawnDistance), new Vector3D(gridPosition + spawnDistance))); } } } entities.Clear(); }
void UpdateBoundingFrustum() { // Update frustum BoundingFrustum.Matrix = ViewProjectionMatrix; // Update bounding box BoundingBox = BoundingBoxD.CreateInvalid(); BoundingBox.Include(ref BoundingFrustum); // Update bounding sphere BoundingSphere = MyUtils.GetBoundingSphereFromBoundingBox(ref BoundingBox); }
public bool Update() { if (!Enabled) return AutoDelete; //efect is not enabled at all and must be deleted System.Diagnostics.Debug.Assert(WorldMatrix != MatrixD.Zero, "Effect world matrix was not set!"); if (!m_isPreloading && !m_wasPreloaded && m_preload > 0) { m_isPreloading = true; // TODO: Optimize (preload causes lags, depending on preload size, it's from 0 ms to 85 ms) while (m_elapsedTime < m_preload) { Update(); } m_isPreloading = false; m_wasPreloaded = true; } VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("ParticleEffect-Update"); if (!m_isPreloading && IsInFrustum) { MyPerformanceCounter.PerCameraDrawWrite.ParticleEffectsDrawn++; } VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock(); VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("ParticleEffect-UpdateGen"); m_elapsedTime += MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS; //m_distance = MySector.MainCamera.GetDistanceWithFOV(WorldMatrix.Translation) / (100.0f); //precalculate for LODs m_distance = (float)Vector3D.Distance(MyTransparentGeometry.Camera.Translation, WorldMatrix.Translation) / (100.0f); //precalculate for LODs m_particlesCount = 0; m_birthRate = 0; m_AABB = BoundingBoxD.CreateInvalid(); //if (CalculateDeltaMatrix) //{ //DeltaMatrix = Matrix.Invert(m_lastWorldMatrix) * m_worldMatrix; //} if (Velocity != Vector3.Zero) { var position = m_worldMatrix.Translation; position.X += Velocity.X * MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS; position.Y += Velocity.Y * MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS; position.Z += Velocity.Z * MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS; m_worldMatrix = MatrixD.CreateWorld(position, Vector3D.Normalize(Velocity), m_worldMatrix.Up); } //if (RenderCounter == 0 || ((MyRender.RenderCounter - RenderCounter) < FRAMES_TO_SKIP)) //more than FRAMES_TO_SKIP frames consider effect as invisible { foreach (MyParticleGeneration generation in m_generations) { generation.EffectMatrix = WorldMatrix; generation.Update(); m_particlesCount += generation.GetParticlesCount(); m_birthRate += generation.GetBirthRate(); BoundingBoxD bbox = generation.GetAABB(); m_AABB = m_AABB.Include(ref bbox); } if (m_particlesCount > 0) m_hasShownSomething = true; //TODO IsInFrustum = true; // MySector.MainCamera.IsInFrustum(ref m_AABB); } VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock(); m_lastWorldMatrix = m_worldMatrix; if (((m_particlesCount == 0 && HasShownSomething()) || (m_particlesCount == 0 && m_birthRate == 0.0f)) && AutoDelete && !m_isPreloading) { //Effect was played and has to be deleted return true; } if (!m_isPreloading && OnUpdate != null) OnUpdate(this, null); return false; }
private void UpdateParticlesLife() { int counter = 0; VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("ParticleGeneration-UpdateParticlesLife"); MyParticleGeneration inheritedGeneration = null; Vector3D previousParticlePosition = m_effect.WorldMatrix.Translation; float particlesToCreate = 0; m_AABB = BoundingBoxD.CreateInvalid(); m_AABB = m_AABB.Include(ref previousParticlePosition); if (OnDie.GetValue <int>() != -1) { inheritedGeneration = GetInheritedGeneration(OnDie.GetValue <int>()); if (inheritedGeneration == null) { OnDie.SetValue(-1); } else { inheritedGeneration.IsInherited = true; particlesToCreate = inheritedGeneration.m_particlesToCreate; } } VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock(); VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("ParticleGeneration-Update01"); Vector3D previousTrail0 = previousParticlePosition; Vector3D previousTrail1 = previousParticlePosition; using (ParticlesLock.AcquireExclusiveUsing()) { while (counter < m_particles.Count) { float motionInheritance; MotionInheritance.GetInterpolatedValue(m_effect.GetElapsedTime(), out motionInheritance); MyAnimatedParticle particle = m_particles[counter]; if (motionInheritance > 0) { m_effect.CalculateDeltaMatrix = true; } if (particle.Update()) { if (motionInheritance > 0) { var delta = m_effect.GetDeltaMatrix(); particle.AddMotionInheritance(ref motionInheritance, ref delta); } if (counter == 0) { previousParticlePosition = particle.ActualPosition; previousTrail0 = particle.Quad.Point1; previousTrail1 = particle.Quad.Point2; particle.Quad.Point0 = particle.ActualPosition; particle.Quad.Point2 = particle.ActualPosition; } counter++; if (particle.Type == MyParticleTypeEnum.Trail) { if (particle.ActualPosition == previousParticlePosition) { particle.Quad.Point0 = particle.ActualPosition; particle.Quad.Point1 = particle.ActualPosition; particle.Quad.Point2 = particle.ActualPosition; particle.Quad.Point3 = particle.ActualPosition; } else { MyPolyLineD polyLine = new MyPolyLineD(); polyLine.Thickness = particle.Thickness; polyLine.Point0 = particle.ActualPosition; polyLine.Point1 = previousParticlePosition; Vector3D direction = polyLine.Point1 - polyLine.Point0; Vector3D normalizedDirection = MyUtils.Normalize(polyLine.Point1 - polyLine.Point0); polyLine.LineDirectionNormalized = normalizedDirection; var camPos = MyTransparentGeometry.Camera.Translation; MyUtils.GetPolyLineQuad(out particle.Quad, ref polyLine, camPos); particle.Quad.Point0 = previousTrail0 + direction * 0.15f; particle.Quad.Point3 = previousTrail1 + direction * 0.15f; previousTrail0 = particle.Quad.Point1; previousTrail1 = particle.Quad.Point2; } } previousParticlePosition = particle.ActualPosition; m_AABB = m_AABB.Include(ref previousParticlePosition); particle.Flags = GetEffect().IsInFrustum ? particle.Flags | MyAnimatedParticle.ParticleFlags.IsInFrustum : particle.Flags & ~MyAnimatedParticle.ParticleFlags.IsInFrustum; continue; } if (inheritedGeneration != null) { inheritedGeneration.m_particlesToCreate = particlesToCreate; inheritedGeneration.EffectMatrix = MatrixD.CreateWorld(particle.ActualPosition, Vector3D.Normalize(particle.Velocity), Vector3D.Cross(Vector3D.Left, particle.Velocity)); inheritedGeneration.UpdateParticlesCreation(); } m_particles.Remove(particle); MyTransparentGeometry.DeallocateAnimatedParticle(particle); } } VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock(); }
public void TestVoxelNavmeshTriangle(ref Vector3D a, ref Vector3D b, ref Vector3D c, List <MyCubeGrid> gridsToTest, List <MyGridPathfinding.CubeId> linkCandidatesOutput, out bool intersecting) { ProfilerShort.Begin("TestVoxelNavmeshTriangle"); ProfilerShort.Begin("Triangle-obstacle tests"); Vector3D s = (a + b + c) / 3.0; if (m_obstacles.IsInObstacle(s)) { intersecting = true; ProfilerShort.End(); ProfilerShort.End(); return; } ProfilerShort.End(); BoundingBoxD triBB; Vector3D aLocal, bLocal, cLocal, gLocal; Vector3D g = Vector3D.Zero; if (MyPerGameSettings.NavmeshPresumesDownwardGravity) { g = Vector3.Down * 2.0f; } m_tmpLinkCandidates.Clear(); intersecting = false; foreach (var grid in gridsToTest) { MatrixD mat = grid.PositionComp.WorldMatrixNormalizedInv; Vector3D.Transform(ref a, ref mat, out aLocal); Vector3D.Transform(ref b, ref mat, out bLocal); Vector3D.Transform(ref c, ref mat, out cLocal); Vector3D.TransformNormal(ref g, ref mat, out gLocal); triBB = new BoundingBoxD(Vector3D.MaxValue, Vector3D.MinValue); triBB.Include(ref aLocal, ref bLocal, ref cLocal); Vector3I min = grid.LocalToGridInteger(triBB.Min); Vector3I max = grid.LocalToGridInteger(triBB.Max); Vector3I pos = min - Vector3I.One; Vector3I max2 = max + Vector3I.One; for (var it = new Vector3I_RangeIterator(ref pos, ref max2); it.IsValid(); it.GetNext(out pos)) { if (grid.GetCubeBlock(pos) != null) { Vector3 largeMin = (pos - Vector3.One) * grid.GridSize; Vector3 largeMax = (pos + Vector3.One) * grid.GridSize; Vector3 smallMin = (pos - Vector3.Half) * grid.GridSize; Vector3 smallMax = (pos + Vector3.Half) * grid.GridSize; BoundingBoxD largeBb = new BoundingBoxD(largeMin, largeMax); BoundingBoxD bb = new BoundingBoxD(smallMin, smallMax); largeBb.Include(largeMin + gLocal); largeBb.Include(largeMax + gLocal); bb.Include(smallMin + gLocal); bb.Include(smallMax + gLocal); ProfilerShort.Begin("Triangle intersection tests"); if (largeBb.IntersectsTriangle(ref aLocal, ref bLocal, ref cLocal)) { if (bb.IntersectsTriangle(ref aLocal, ref bLocal, ref cLocal)) { intersecting = true; ProfilerShort.End(); break; } else { int dx = Math.Min(Math.Abs(min.X - pos.X), Math.Abs(max.X - pos.X)); int dy = Math.Min(Math.Abs(min.Y - pos.Y), Math.Abs(max.Y - pos.Y)); int dz = Math.Min(Math.Abs(min.Z - pos.Z), Math.Abs(max.Z - pos.Z)); if ((dx + dy + dz) < 3) { m_tmpLinkCandidates.Add(new MyGridPathfinding.CubeId() { Grid = grid, Coords = pos }); } } } ProfilerShort.End(); } } if (intersecting) { break; } } if (!intersecting) { for (int i = 0; i < m_tmpLinkCandidates.Count; ++i) { linkCandidatesOutput.Add(m_tmpLinkCandidates[i]); } } m_tmpLinkCandidates.Clear(); ProfilerShort.End(); }
//1. Object A reaches borders //2. Make ideal cluster box B around A //3. Detect all cluster intersections C of B //4. Make union of all C and B to D //5. Find best division of D //6. Foreach dominant axis //6A split until only allowed size //6B leave lowest larger size //repeat 6 until dominant axis is allowed size or not splittable public void ReorderClusters(BoundingBoxD aabb, ulong objectId) { //1+2 aabb.InflateToMinimum(IdealClusterSize); bool isBoxSafe = false; BoundingBoxD unionCluster = aabb; //3 m_clusterTree.OverlapAllBoundingBox(ref unionCluster, m_resultList); HashSet <MyObjectData> objectsInUnion = new HashSet <MyObjectData>(); while (!isBoxSafe) { //4 objectsInUnion.Clear(); objectsInUnion.Add(m_objectsData[objectId]); foreach (MyCluster collidedCluster in m_resultList) { unionCluster.Include(collidedCluster.AABB); foreach (var ob in m_objectsData.Where(x => collidedCluster.Objects.Contains(x.Key)).Select(x => x.Value)) { objectsInUnion.Add(ob); } } int oldClustersCount = m_resultList.Count; //3 m_clusterTree.OverlapAllBoundingBox(ref unionCluster, m_resultList); isBoxSafe = oldClustersCount == m_resultList.Count; //Box is safe only if no new clusters were added m_staticTree.OverlapAllBoundingBox(ref unionCluster, m_objectDataResultList); foreach (var ob in m_objectDataResultList) { if (m_objectsData[ob].Cluster != null) { if (!m_resultList.Contains(m_objectsData[ob].Cluster)) { unionCluster.Include(m_objectsData[ob].Cluster.AABB); isBoxSafe = false; } } } } m_staticTree.OverlapAllBoundingBox(ref unionCluster, m_objectDataResultList); foreach (var ob in m_objectDataResultList) { //var c = m_objectsData[ob].Cluster.AABB.Contains(unionCluster); System.Diagnostics.Debug.Assert(m_objectsData[ob].Cluster == null || m_objectsData[ob].Cluster.AABB.Contains(m_objectsData[ob].AABB) != ContainmentType.Disjoint, "Clusters failure"); System.Diagnostics.Debug.Assert(m_objectsData[ob].Cluster == null || (m_clusters.Contains(m_objectsData[ob].Cluster) && m_resultList.Contains(m_objectsData[ob].Cluster)), "Static object is not inside found clusters"); objectsInUnion.Add(m_objectsData[ob]); } #if DEBUG foreach (var ob in objectsInUnion) { System.Diagnostics.Debug.Assert(ob.Cluster == null || (m_clusters.Contains(ob.Cluster) && m_resultList.Contains(ob.Cluster)), "There is object not belonging to found cluster!"); } #endif //5 Stack <MyClusterDescription> clustersToDivide = new Stack <MyClusterDescription>(); List <MyClusterDescription> finalClusters = new List <MyClusterDescription>(); var unionClusterDesc = new MyClusterDescription() { AABB = unionCluster, DynamicObjects = objectsInUnion.Where(x => x.ActivationHandler == null || !x.ActivationHandler.IsStaticForCluster).ToList(), StaticObjects = objectsInUnion.Where(x => (x.ActivationHandler != null) && x.ActivationHandler.IsStaticForCluster).ToList(), }; clustersToDivide.Push(unionClusterDesc); var staticObjectsToRemove = unionClusterDesc.StaticObjects.Where(x => x.Cluster != null).ToList(); var staticObjectsTotal = unionClusterDesc.StaticObjects.Count; while (clustersToDivide.Count > 0) { MyClusterDescription desc = clustersToDivide.Pop(); if (desc.DynamicObjects.Count == 0) { continue; } //minimal valid aabb usable for this cluster BoundingBoxD minimumCluster = BoundingBoxD.CreateInvalid(); for (int i = 0; i < desc.DynamicObjects.Count; i++) { MyObjectData objectData0 = desc.DynamicObjects[i]; BoundingBoxD aabb0 = objectData0.AABB.GetInflated(IdealClusterSize / 2); minimumCluster.Include(aabb0); } //Divide along longest axis BoundingBoxD dividedCluster = minimumCluster; Vector3D currentMax = minimumCluster.Max; int longestAxis = minimumCluster.Size.AbsMaxComponent(); switch (longestAxis) { case 0: desc.DynamicObjects.Sort(AABBComparerX.Static); break; case 1: desc.DynamicObjects.Sort(AABBComparerY.Static); break; case 2: desc.DynamicObjects.Sort(AABBComparerZ.Static); break; } bool isClusterSplittable = false; if (minimumCluster.Size.AbsMax() >= MaximumForSplit.AbsMax()) { for (int i = 1; i < desc.DynamicObjects.Count; i++) { MyObjectData objectData0 = desc.DynamicObjects[i - 1]; MyObjectData objectData1 = desc.DynamicObjects[i]; BoundingBoxD aabb0 = objectData0.AABB.GetInflated(IdealClusterSize / 2); BoundingBoxD aabb1 = objectData1.AABB.GetInflated(IdealClusterSize / 2); //two neigbour object have distance between them bigger than minimum if ((aabb1.Min.GetDim(longestAxis) - aabb0.Max.GetDim(longestAxis)) > 0) { System.Diagnostics.Debug.Assert(aabb0.Max.GetDim(longestAxis) - minimumCluster.Min.GetDim(longestAxis) > 0, "Invalid minimal cluster"); isClusterSplittable = true; currentMax.SetDim(longestAxis, aabb0.Max.GetDim(longestAxis)); break; } } } dividedCluster.Max = currentMax; dividedCluster.InflateToMinimum(IdealClusterSize); MyClusterDescription dividedClusterDesc = new MyClusterDescription() { AABB = dividedCluster, DynamicObjects = new List <MyObjectData>(), StaticObjects = new List <MyObjectData>(), }; foreach (var dynObj in desc.DynamicObjects.ToList()) { var cont = dividedCluster.Contains(dynObj.AABB); if (cont == ContainmentType.Contains) { dividedClusterDesc.DynamicObjects.Add(dynObj); desc.DynamicObjects.Remove(dynObj); } System.Diagnostics.Debug.Assert(cont != ContainmentType.Intersects, "Cannot split clusters in the middle of objects"); } foreach (var statObj in desc.StaticObjects.ToList()) { var cont = dividedCluster.Contains(statObj.AABB); if ((cont == ContainmentType.Contains) || (cont == ContainmentType.Intersects)) { dividedClusterDesc.StaticObjects.Add(statObj); desc.StaticObjects.Remove(statObj); } } dividedClusterDesc.AABB = dividedCluster; if (desc.DynamicObjects.Count > 0) { BoundingBoxD restCluster = BoundingBoxD.CreateInvalid(); foreach (var restbb in desc.DynamicObjects) { restCluster.Include(restbb.AABB.GetInflated(MinimumDistanceFromBorder)); } restCluster.InflateToMinimum(IdealClusterSize); MyClusterDescription restClusterDesc = new MyClusterDescription() { AABB = restCluster, DynamicObjects = desc.DynamicObjects.ToList(), StaticObjects = desc.StaticObjects.ToList(), }; if (restClusterDesc.AABB.Size.AbsMax() > 2 * IdealClusterSize.AbsMax()) { clustersToDivide.Push(restClusterDesc); } else { finalClusters.Add(restClusterDesc); } } if (dividedClusterDesc.AABB.Size.AbsMax() > 2 * IdealClusterSize.AbsMax() && isClusterSplittable) { clustersToDivide.Push(dividedClusterDesc); } else { finalClusters.Add(dividedClusterDesc); } } #if DEBUG //Check consistency for (int i = 0; i < finalClusters.Count; i++) { for (int j = 0; j < finalClusters.Count; j++) { if (i != j) { var cont = finalClusters[i].AABB.Contains(finalClusters[j].AABB); System.Diagnostics.Debug.Assert(cont == ContainmentType.Disjoint, "Overlapped clusters!"); if (cont != ContainmentType.Disjoint) { } } } } #endif #if DEBUG Dictionary <MyCluster, List <ulong> > objectsPerRemovedCluster = new Dictionary <MyCluster, List <ulong> >(); Dictionary <MyCluster, List <ulong> > dynamicObjectsInCluster = new Dictionary <MyCluster, List <ulong> >(); foreach (var finalCluster in finalClusters) { foreach (var ob in finalCluster.DynamicObjects) { if (ob.Cluster != null) { if (!objectsPerRemovedCluster.ContainsKey(ob.Cluster)) { objectsPerRemovedCluster[ob.Cluster] = new List <ulong>(); } objectsPerRemovedCluster[ob.Cluster].Add(ob.Id); } else { } } } foreach (var removingCluster in objectsPerRemovedCluster) { dynamicObjectsInCluster[removingCluster.Key] = new List <ulong>(); foreach (var ob in removingCluster.Key.Objects) { if (!m_objectsData[ob].ActivationHandler.IsStaticForCluster) { dynamicObjectsInCluster[removingCluster.Key].Add(ob); } } System.Diagnostics.Debug.Assert(removingCluster.Value.Count == dynamicObjectsInCluster[removingCluster.Key].Count, "Not all objects from removing cluster are going to new clusters!"); } Dictionary <MyCluster, List <ulong> > staticObjectsInCluster = new Dictionary <MyCluster, List <ulong> >(); foreach (var staticObj in staticObjectsToRemove) { System.Diagnostics.Debug.Assert(staticObj.Cluster != null, "Where to remove?"); if (!staticObjectsInCluster.ContainsKey(staticObj.Cluster)) { staticObjectsInCluster[staticObj.Cluster] = new List <ulong>(); } staticObjectsInCluster[staticObj.Cluster].Add(staticObj.Id); } #endif HashSet <MyCluster> oldClusters = new HashSet <MyCluster>(); HashSet <MyCluster> newClusters = new HashSet <MyCluster>(); foreach (var staticObj in staticObjectsToRemove) { if (staticObj.Cluster != null) { oldClusters.Add(staticObj.Cluster); RemoveObjectFromCluster(staticObj, true); } else { } } foreach (var staticObj in staticObjectsToRemove) { if (staticObj.Cluster != null) { staticObj.ActivationHandler.FinishRemoveBatch(staticObj.Cluster.UserData); staticObj.Cluster = null; } } int staticObjectsAdded = 0; //Move objects from old clusters to new clusters, use batching foreach (var finalCluster in finalClusters) { BoundingBoxD clusterAABB = finalCluster.AABB; MyCluster newCluster = CreateCluster(ref clusterAABB); #if DEBUG for (int i = 0; i < finalCluster.DynamicObjects.Count; i++) { for (int j = 0; j < finalCluster.DynamicObjects.Count; j++) { if (i != j) { System.Diagnostics.Debug.Assert(finalCluster.DynamicObjects[i].Id != finalCluster.DynamicObjects[j].Id); } } } #endif foreach (var obj in finalCluster.DynamicObjects) { if (obj.Cluster != null) { oldClusters.Add(obj.Cluster); RemoveObjectFromCluster(obj, true); } else { System.Diagnostics.Debug.Assert(objectId == obj.Id || obj.ActivationHandler.IsStaticForCluster, "Dynamic object must have cluster"); } } foreach (var obj in finalCluster.DynamicObjects) { if (obj.Cluster != null) { obj.ActivationHandler.FinishRemoveBatch(obj.Cluster.UserData); obj.Cluster = null; } } //Finish batches on old worlds and remove old worlds foreach (MyCluster oldCluster in oldClusters) { if (OnFinishBatch != null) { OnFinishBatch(oldCluster.UserData); } } foreach (var obj in finalCluster.DynamicObjects) { AddObjectToCluster(newCluster, obj.Id, true); } foreach (var obj in finalCluster.StaticObjects) { if (newCluster.AABB.Contains(obj.AABB) != ContainmentType.Disjoint) { AddObjectToCluster(newCluster, obj.Id, true); staticObjectsAdded++; } } newClusters.Add(newCluster); } System.Diagnostics.Debug.Assert(staticObjectsTotal >= staticObjectsAdded, "Static objects appeared out of union"); #if DEBUG //foreach (var finalCluster in finalClusters) //{ // foreach (var obj in finalCluster.DynamicObjects) // { // System.Diagnostics.Debug.Assert(!oldClusters.Contains(obj.Cluster), "Object was not added to correct cluster"); // } //} //foreach (var objectData in m_objectsData) //{ // if (!objectData.Value.ActivationHandler.IsStaticForCluster) // System.Diagnostics.Debug.Assert(!oldClusters.Contains(objectData.Value.Cluster)); //} //foreach (var objectData in m_objectsData) //{ // if (!objectData.Value.ActivationHandler.IsStaticForCluster) // System.Diagnostics.Debug.Assert(m_clusters.Contains(objectData.Value.Cluster)); //} #endif foreach (MyCluster oldCluster in oldClusters) { RemoveCluster(oldCluster); } //Finish batches on new world and their objects foreach (MyCluster newCluster in newClusters) { if (OnFinishBatch != null) { OnFinishBatch(newCluster.UserData); } foreach (var ob in newCluster.Objects) { if (m_objectsData[ob].ActivationHandler != null) { m_objectsData[ob].ActivationHandler.FinishAddBatch(); } } } }
public void TestVoxelNavmeshTriangle(ref Vector3D a, ref Vector3D b, ref Vector3D c, List <MyCubeGrid> gridsToTest, List <MyGridPathfinding.CubeId> linkCandidatesOutput, out bool intersecting) { Vector3D point = ((a + b) + c) / 3.0; if (this.m_obstacles.IsInObstacle(point)) { intersecting = true; return; } Vector3D zero = Vector3D.Zero; if (MyPerGameSettings.NavmeshPresumesDownwardGravity) { zero = Vector3.Down * 2f; } m_tmpLinkCandidates.Clear(); intersecting = false; using (List <MyCubeGrid> .Enumerator enumerator = gridsToTest.GetEnumerator()) { goto TR_0016; TR_0008: if (intersecting) { goto TR_0006; } TR_0016: while (true) { if (enumerator.MoveNext()) { Vector3D vectord2; Vector3D vectord3; Vector3D vectord4; Vector3D vectord5; MyCubeGrid current = enumerator.Current; MatrixD worldMatrixNormalizedInv = current.PositionComp.WorldMatrixNormalizedInv; Vector3D.Transform(ref a, ref worldMatrixNormalizedInv, out vectord2); Vector3D.Transform(ref b, ref worldMatrixNormalizedInv, out vectord3); Vector3D.Transform(ref c, ref worldMatrixNormalizedInv, out vectord4); Vector3D.TransformNormal(ref zero, ref worldMatrixNormalizedInv, out vectord5); BoundingBoxD xd = new BoundingBoxD(Vector3D.MaxValue, Vector3D.MinValue); xd.Include(ref vectord2, ref vectord3, ref vectord4); Vector3I vectori = current.LocalToGridInteger((Vector3)xd.Min); Vector3I vectori2 = current.LocalToGridInteger((Vector3)xd.Max); Vector3I start = vectori - Vector3I.One; Vector3I end = (Vector3I)(vectori2 + Vector3I.One); Vector3I_RangeIterator iterator = new Vector3I_RangeIterator(ref start, ref end); while (iterator.IsValid()) { if (current.GetCubeBlock(start) != null) { Vector3 min = (Vector3)((start - Vector3.One) * current.GridSize); Vector3 max = (start + Vector3.One) * current.GridSize; Vector3 vector3 = (Vector3)((start - Vector3.Half) * current.GridSize); Vector3 vector4 = (start + Vector3.Half) * current.GridSize; BoundingBoxD xd3 = new BoundingBoxD(min, max); BoundingBoxD xd4 = new BoundingBoxD(vector3, vector4); xd3.Include(min + vectord5); xd3.Include(max + vectord5); xd4.Include(vector3 + vectord5); xd4.Include(vector4 + vectord5); if (xd3.IntersectsTriangle(ref vectord2, ref vectord3, ref vectord4)) { if (xd4.IntersectsTriangle(ref vectord2, ref vectord3, ref vectord4)) { intersecting = true; break; } int num3 = Math.Min(Math.Abs((int)(vectori.Z - start.Z)), Math.Abs((int)(vectori2.Z - start.Z))); if (((Math.Min(Math.Abs((int)(vectori.X - start.X)), Math.Abs((int)(vectori2.X - start.X))) + Math.Min(Math.Abs((int)(vectori.Y - start.Y)), Math.Abs((int)(vectori2.Y - start.Y)))) + num3) < 3) { MyGridPathfinding.CubeId item = new MyGridPathfinding.CubeId { Grid = current, Coords = start }; m_tmpLinkCandidates.Add(item); } } } iterator.GetNext(out start); } } else { goto TR_0006; } break; } goto TR_0008; } TR_0006: if (!intersecting) { for (int i = 0; i < m_tmpLinkCandidates.Count; i++) { linkCandidatesOutput.Add(m_tmpLinkCandidates[i]); } } m_tmpLinkCandidates.Clear(); }
/// <summary> /// Adds environment item to internal collections. Creates render and physics data. /// </summary> /// <returns>True if successfully added, otherwise false.</returns> private bool AddItem( MyEnvironmentItemDefinition itemDefinition, ref MatrixD worldMatrix, ref BoundingBoxD aabbWorld, bool silentOverlaps = false) { if (!MyFakes.ENABLE_ENVIRONMENT_ITEMS) return true; Debug.Assert(m_definition.ContainsItemDefinition(itemDefinition), String.Format("Environment item with definition '{0}' not found in class '{1}'", itemDefinition.Id, m_definition.Id)); if (!m_definition.ContainsItemDefinition(itemDefinition)) { return false; } if (itemDefinition.Model == null) return false; //MyDefinitionId defId = new MyDefinitionId(envItemObjectBuilderType, subtypeId.ToString()); int modelId = MyEnvironmentItems.GetModelId(itemDefinition.Id.SubtypeId); string modelName = MyModel.GetById(modelId); MyModel model = MyModels.GetModelOnlyData(modelName); if (model == null) { //Debug.Fail(String.Format("Environment item model of '{0}' not found, skipping the item...", itemDefinition.Id)); return false; } CheckModelConsistency(itemDefinition); int localId = worldMatrix.Translation.GetHashCode(); if (m_itemsData.ContainsKey(localId)) { if (!silentOverlaps) { Debug.Fail("More items on same place! " + worldMatrix.Translation.ToString()); MyLog.Default.WriteLine("WARNING: items are on the same place."); } return false; } MyEnvironmentItemData data = new MyEnvironmentItemData() { Id = localId, SubtypeId = itemDefinition.Id.SubtypeId, Transform = new MyTransformD(ref worldMatrix), Enabled = true, SectorInstanceId = -1, Model = model, }; //Preload split planes //VRageRender.MyRenderProxy.PreloadMaterials(model.AssetName); aabbWorld.Include(model.BoundingBox.Transform(worldMatrix)); MatrixD transform = data.Transform.TransformMatrix; float sectorSize = MyFakes.ENVIRONMENT_ITEMS_ONE_INSTANCEBUFFER ? 20000 : m_definition.SectorSize; Vector3I sectorId = MyEnvironmentSector.GetSectorId(transform.Translation - CellsOffset, sectorSize); MyEnvironmentSector sector; if (!m_sectors.TryGetValue(sectorId, out sector)) { sector = new MyEnvironmentSector(sectorId, sectorId * sectorSize + CellsOffset); m_sectors.Add(sectorId, sector); } // Adds instance of the given model. Local matrix specified might be changed internally in renderer. MatrixD sectorOffsetInv = MatrixD.CreateTranslation(-sectorId * sectorSize - CellsOffset); Matrix transformL = (Matrix)(data.Transform.TransformMatrix * sectorOffsetInv); data.SectorInstanceId = sector.AddInstance(itemDefinition.Id.SubtypeId, modelId, localId, ref transformL, model.BoundingBox, m_instanceFlags, m_definition.MaxViewDistance); data.Transform = new MyTransformD(transform); m_itemsData.Add(localId, data); if (ItemAdded != null) { ItemAdded(this, new ItemInfo() { LocalId = localId, SubtypeId = data.SubtypeId, Transform = data.Transform, }); } return true; }
private static void CalculateAABB(ref BoundingBoxD bbox, out float scaleZ, out float scaleXY, ref Vector3D position, ref Vector3D direction, ref Vector3D up, float reflectorConeMaxAngleCos, float reflectorRange) { scaleZ = 1; scaleXY = 1; float cosAngle = 1 - reflectorConeMaxAngleCos; scaleZ = reflectorRange; // Calculate cone side (hypotenuse of triangle) float side = reflectorRange / cosAngle; // Calculate cone bottom scale (Pythagoras theorem) scaleXY = (float)System.Math.Sqrt(side * side - reflectorRange * reflectorRange) * 2; if (scaleXY == 0) scaleXY = 1; up = MyUtils.Normalize(up); Vector3 coneSideDirection = Vector3.Cross(up, direction); coneSideDirection = MyUtils.Normalize(coneSideDirection); Vector3D coneCenter = position + direction * scaleZ; Vector3D pt1 = coneCenter + coneSideDirection * scaleXY / 2 + up * scaleXY / 2; Vector3D pt2 = coneCenter - coneSideDirection * scaleXY / 2 + up * scaleXY / 2; Vector3D pt3 = coneCenter + coneSideDirection * scaleXY / 2 - up * scaleXY / 2; Vector3D pt4 = coneCenter - coneSideDirection * scaleXY / 2 - up * scaleXY / 2; bbox = BoundingBoxD.CreateInvalid(); bbox = bbox.Include(ref position); //bbox = bbox.Include(ref coneCenter); bbox = bbox.Include(ref pt1); bbox = bbox.Include(ref pt2); bbox = bbox.Include(ref pt3); bbox = bbox.Include(ref pt4); }
/// <summary> /// Handles camera collisions with environment /// </summary> /// <param name="controlledEntity"></param> /// <param name="shakeActive"></param> /// <param name="headPosition"></param> /// <param name="headDirection"></param> /// <returns>False if no correct position was found</returns> private bool HandleIntersection(MyEntity controlledEntity, MyOrientedBoundingBoxD safeOBB, bool requireRaycast, bool shakeActive, Vector3D headPosition, Vector3 headDirection) { var line = new LineD(m_target, m_position); var safeOBBLine = new LineD(line.From, line.From + line.Direction * 2 * safeOBB.HalfExtent.Length()); Vector3D castStartSafe; { MyOrientedBoundingBoxD safeObbWithCollisionExtents = new MyOrientedBoundingBoxD(safeOBB.Center, safeOBB.HalfExtent + 2 * CAMERA_RADIUS, safeOBB.Orientation); double?safeIntersection = safeObbWithCollisionExtents.Intersects(ref safeOBBLine); if (!safeIntersection.HasValue) { safeIntersection = safeOBB.HalfExtent.Length(); } double safeDistance = safeIntersection.Value; castStartSafe = line.From + line.Direction * safeDistance; } { double?unsafeIntersection = safeOBB.Intersects(ref safeOBBLine); if (!requireRaycast && unsafeIntersection.HasValue) { var castStartUnsafe = line.From + line.Direction * unsafeIntersection.Value; var castEndUnsafe = castStartSafe + line.Direction; // short raycast, not causing problems with asteroids generating geometry Physics.MyPhysics.CastRay(castStartUnsafe, castEndUnsafe, m_raycastList, MyPhysics.CollisionLayers.CharacterCollisionLayer); if (!IsRaycastOK(m_raycastList)) { return(false); } } } if (requireRaycast) { // short raycast, not causing problems with asteroids generating geometry Physics.MyPhysics.CastRay(line.From, castStartSafe + line.Direction, m_raycastList, MyPhysics.CollisionLayers.CharacterCollisionLayer); if (!IsRaycastOK(m_raycastList)) { return(false); } } HkShape shape = new HkSphereShape(CAMERA_RADIUS); try { // small shape, not causing problems with asteroids generating geometry Physics.MyPhysics.GetPenetrationsShape(shape, ref castStartSafe, ref Quaternion.Identity, m_rigidList, MyPhysics.CollisionLayers.CharacterCollisionLayer); if (m_rigidList.Count > 0) { bool sameGrid = false; if (MySession.Static.ControlledEntity != null && m_rigidList[0].Body != null) { sameGrid = m_rigidList[0].GetCollisionEntity() == MySession.Static.ControlledEntity; } if (sameGrid) { castStartSafe += line.Direction; } } var shapeCastLine = new LineD(castStartSafe, m_position); uint steps = 1; uint stepIdx = 0; if (shapeCastLine.Length > SHAPE_CAST_STEP) { steps = (uint)Math.Ceiling(shapeCastLine.Length / SHAPE_CAST_STEP); if (steps >= SHAPE_CAST_MAX_STEP_COUNT) { steps = SHAPE_CAST_MAX_STEP_COUNT - 1; } stepIdx = m_updateCount % steps; m_lastShapeCastDistance[stepIdx] = float.PositiveInfinity; Vector3D step = shapeCastLine.Direction * (shapeCastLine.Length / steps); shapeCastLine = new LineD(castStartSafe + stepIdx * step, castStartSafe + (stepIdx + 1) * step); } if (false) { BoundingBoxD bbox = BoundingBoxD.CreateInvalid(); bbox.Include(new BoundingSphereD(shapeCastLine.From, CAMERA_RADIUS)); bbox.Include(new BoundingSphereD(shapeCastLine.To, CAMERA_RADIUS)); VRageRender.MyRenderProxy.DebugDrawAABB(bbox, Color.Crimson, 1f, 1f, true); } var matrix = MatrixD.CreateTranslation(shapeCastLine.From); HkContactPointData?cpd; if (controlledEntity.Physics != null && controlledEntity.GetPhysicsBody().CharacterProxy != null) { cpd = MyPhysics.CastShapeReturnContactData(shapeCastLine.To, shape, ref matrix, MyPhysics.CollisionLayers.CharacterCollisionLayer, 0.0f); } else { cpd = MyPhysics.CastShapeReturnContactData(shapeCastLine.To, shape, ref matrix, MyPhysics.CollisionLayers.DefaultCollisionLayer, 0.0f); } if (cpd.HasValue) { var point = shapeCastLine.From + shapeCastLine.Direction * shapeCastLine.Length * cpd.Value.DistanceFraction; m_lastShapeCastDistance[stepIdx] = (float)(castStartSafe - point).Length(); } else { m_lastShapeCastDistance[stepIdx] = float.PositiveInfinity; } float?dist = null; for (int i = 0; i < steps; ++i) { if (m_lastShapeCastDistance[i] != float.PositiveInfinity) { dist = Math.Min(m_lastShapeCastDistance[i], dist ?? float.PositiveInfinity); } } if (dist.HasValue) { if (dist == 0.0f) { return(false); } else { m_positionSafe = castStartSafe + shapeCastLine.Direction * dist.Value; } } else { m_positionSafe = m_position; } return(true); } finally { shape.RemoveReference(); } }
protected void UpdateRenderObject() { m_actualWorldAABB = BoundingBoxD.CreateInvalid(); if (AnimationController.CharacterBones != null) for (int i = 1; i < Model.Bones.Length; i++) { Vector3D p1 = Vector3D.Transform(AnimationController.CharacterBones[i].Parent.AbsoluteTransform.Translation, WorldMatrix); Vector3D p2 = Vector3D.Transform(AnimationController.CharacterBones[i].AbsoluteTransform.Translation, WorldMatrix); m_actualWorldAABB.Include(ref p1); m_actualWorldAABB.Include(ref p2); } ContainmentType containmentType; m_aabb.Contains(ref m_actualWorldAABB, out containmentType); if (containmentType != ContainmentType.Contains) { m_actualWorldAABB.Inflate(0.5f); MatrixD worldMatrix = WorldMatrix; VRageRender.MyRenderProxy.UpdateRenderObject(Render.RenderObjectIDs[0], ref worldMatrix, false, m_actualWorldAABB); m_aabb = m_actualWorldAABB; } }