private void CutTree(int itemInstanceId, Vector3D hitWorldPosition, Vector3 hitNormal, float forceMultiplier = 1.0f) { HkStaticCompoundShape shape = (HkStaticCompoundShape)Physics.RigidBody.GetShape(); int physicsInstanceId; if (m_localIdToPhysicsShapeInstanceId.TryGetValue(itemInstanceId, out physicsInstanceId)) { MyEnvironmentItemData itemData = m_itemsData[itemInstanceId]; MyDefinitionId id = new MyDefinitionId(Definition.ItemDefinitionType, itemData.SubtypeId); var itemDefinition = (MyTreeDefinition)MyDefinitionManager.Static.GetEnvironmentItemDefinition(id); //Remove static tree if (RemoveItem(itemInstanceId, physicsInstanceId, sync: true, immediateUpdate: true) && itemDefinition != null && itemDefinition.BreakSound != null && itemDefinition.BreakSound.Length > 0) { MyMultiplayer.RaiseStaticEvent(s => PlaySound, hitWorldPosition, itemDefinition.BreakSound); } //Create fractured tree if (MyPerGameSettings.Destruction && VRage.Game.Models.MyModels.GetModelOnlyData(itemDefinition.Model).HavokBreakableShapes != null) { if (itemDefinition.FallSound != null && itemDefinition.FallSound.Length > 0) { CreateBreakableShape(itemDefinition, ref itemData, ref hitWorldPosition, hitNormal, forceMultiplier, itemDefinition.FallSound); } else { CreateBreakableShape(itemDefinition, ref itemData, ref hitWorldPosition, hitNormal, forceMultiplier); } } } }
private bool DisableRenderInstanceIfInRadius(Vector3D center, double radiusSq, int itemInstanceId, bool hasPhysics = false) { MyEnvironmentItemData itemData = m_itemsData[itemInstanceId]; Vector3 translation = itemData.Transform.Position; if (Vector3D.DistanceSquared(new Vector3D(translation), center) <= radiusSq) { int physicsInstanceId; bool itemRemoved = false; if (m_localIdToPhysicsShapeInstanceId.TryGetValue(itemInstanceId, out physicsInstanceId)) { m_physicsShapeInstanceIdToLocalId.Remove(physicsInstanceId); m_localIdToPhysicsShapeInstanceId.Remove(itemInstanceId); itemRemoved = true; } if (!hasPhysics || itemRemoved) { Vector3I sectorId = MyEnvironmentSector.GetSectorId(translation, m_definition.SectorSize); bool disabled = Sectors[sectorId].DisableInstance(itemData.SectorInstanceId, itemData.ModelId); Debug.Assert(disabled, "Env. item render not disabled"); if (disabled) { m_updatedSectorsTmp.Add(sectorId); itemData.Enabled = false; m_itemsData[itemInstanceId] = itemData; } return(true); } } return(false); }
protected bool RemoveItem(int itemInstanceId, int physicsInstanceId, bool sync) { Debug.Assert(sync == false || Sync.IsServer, "Synchronizing env. item removal from the client is forbidden!"); Debug.Assert(m_physicsShapeInstanceIdToLocalId.ContainsKey(physicsInstanceId), "Could not find env. item shape!"); Debug.Assert(m_localIdToPhysicsShapeInstanceId.ContainsKey(itemInstanceId), "Could not find env. item instance!"); m_physicsShapeInstanceIdToLocalId.Remove(physicsInstanceId); m_localIdToPhysicsShapeInstanceId.Remove(itemInstanceId); MyEnvironmentItemData itemData = m_itemsData[itemInstanceId]; itemData.Enabled = false; m_itemsData[itemInstanceId] = itemData; HkStaticCompoundShape shape = (HkStaticCompoundShape)Physics.RigidBody.GetShape(); var shapeKey = shape.ComposeShapeKey(physicsInstanceId, 0); shape.EnableShapeKey(shapeKey, false); Matrix matrix = itemData.Transform.TransformMatrix; var sectorId = MyEnvironmentSector.GetSectorId(matrix.Translation - m_cellsOffset, Definition.SectorSize); var disabled = Sectors[sectorId].DisableInstance(itemData.SectorInstanceId, itemData.ModelId); Debug.Assert(disabled, "Env. item instance render not disabled"); Sectors[sectorId].UpdateRenderInstanceData(); OnRemoveItem(itemInstanceId, ref matrix, itemData.SubtypeId); if (sync) { MySyncEnvironmentItems.RemoveEnvironmentItem(EntityId, itemInstanceId); } return(true); }
protected bool RemoveNonPhysicalItem(int itemInstanceId, bool sync) { Debug.Assert(sync == false || Sync.IsServer, "Synchronizing env. item removal from the client is forbidden!"); Debug.Assert(m_itemsData.ContainsKey(itemInstanceId), "Could not find env. item shape!"); MyEnvironmentItemData itemData = m_itemsData[itemInstanceId]; itemData.Enabled = false; m_itemsData[itemInstanceId] = itemData; Matrix matrix = itemData.Transform.TransformMatrix; var sectorId = MyEnvironmentSector.GetSectorId(matrix.Translation, Definition.SectorSize); var disabled = Sectors[sectorId].DisableInstance(itemData.SectorInstanceId, itemData.ModelId); Debug.Assert(disabled, "Env. item instance render not disabled"); Sectors[sectorId].UpdateRenderInstanceData(); OnRemoveItem(itemInstanceId, ref matrix, itemData.SubtypeId); if (sync) { MySyncEnvironmentItems.RemoveEnvironmentItem(EntityId, itemInstanceId); } return(true); }
public MyEnvironmentItemDefinition GetItemDefinition(int itemInstanceId) { MyEnvironmentItemData itemData = m_itemsData[itemInstanceId]; MyDefinitionId defId = new MyDefinitionId(m_definition.ItemDefinitionType, itemData.SubtypeId); return(MyDefinitionManager.Static.GetEnvironmentItemDefinition(defId) as MyEnvironmentItemDefinition); }
public bool GetItemWorldMatrix(int itemInstanceId, out MatrixD worldMatrix) { worldMatrix = MatrixD.Identity; MyEnvironmentItemData itemData = m_itemsData[itemInstanceId]; worldMatrix = itemData.Transform.TransformMatrix; return(true); }
public MyEnvironmentItemDefinition GetItemDefinitionFromShapeKey(uint shapeKey) { int itemInstanceId = GetItemInstanceId(shapeKey); if (itemInstanceId == -1) { return(null); } MyEnvironmentItemData itemData = m_itemsData[itemInstanceId]; MyDefinitionId defId = new MyDefinitionId(m_definition.ItemDefinitionType, itemData.SubtypeId); return(MyDefinitionManager.Static.GetEnvironmentItemDefinition(defId) as MyEnvironmentItemDefinition); }
protected override MyEntity DestroyItem(int itemInstanceId) { int physicsInstanceId; if (!m_localIdToPhysicsShapeInstanceId.TryGetValue(itemInstanceId, out physicsInstanceId)) { physicsInstanceId = -1; } //Remove static tree MyEnvironmentItemData itemData = m_itemsData[itemInstanceId]; RemoveItem(itemInstanceId, physicsInstanceId, sync: false, immediateUpdate: true); ProfilerShort.Begin("Spawning tree"); // This is for SE when you hit a tree, it will create a floating object with the same model. In case it affects ME, it may be changed. Contact DusanA for it. Debug.Assert(MyPerGameSettings.Game == GameEnum.SE_GAME); //MyPhysicalInventoryItem Item = new MyPhysicalInventoryItem() { Amount = 1, Scale = 1f, Content = new MyObjectBuilder_TreeObject() { SubtypeName = itemData.SubtypeId.ToString() } }; Vector3D pos = itemData.Transform.Position; var s = itemData.Model.AssetName.Insert(itemData.Model.AssetName.Length - 4, "_broken"); MyEntity debris; bool hasBrokenModel = false; if (VRage.Game.Models.MyModels.GetModelOnlyData(s) != null) { hasBrokenModel = true; debris = MyDebris.Static.CreateDebris(s); } else { debris = MyDebris.Static.CreateDebris(itemData.Model.AssetName); } var debrisLogic = (debris.GameLogic as Sandbox.Game.Entities.Debris.MyDebrisBase.MyDebrisBaseLogic); debrisLogic.RandomScale = 1; debrisLogic.LifespanInMiliseconds = BrokenTreeLifeSpan; var m = MatrixD.CreateFromQuaternion(itemData.Transform.Rotation); m.Translation = pos + m.Up * (hasBrokenModel ? 0 : 5); debrisLogic.Start(m, Vector3.Zero, 1, false); //MyFloatingObjects.Spawn(Item, pos + gravity, MyUtils.GetRandomPerpendicularVector(ref gravity), gravity); ProfilerShort.End(); return(debris); }
private void CutTree(int itemInstanceId, Vector3D hitWorldPosition, Vector3 hitNormal, float forceMultiplier = 1.0f) { HkStaticCompoundShape shape = (HkStaticCompoundShape)Physics.RigidBody.GetShape(); int physicsInstanceId; if (m_localIdToPhysicsShapeInstanceId.TryGetValue(itemInstanceId, out physicsInstanceId)) { //Remove static tree MyEnvironmentItemData itemData = m_itemsData[itemInstanceId]; RemoveItem(itemInstanceId, physicsInstanceId, sync: true, immediateUpdate: true); //Create fractured tree MyDefinitionId id = new MyDefinitionId(Definition.ItemDefinitionType, itemData.SubtypeId); var itemDefinition = MyDefinitionManager.Static.GetEnvironmentItemDefinition(id); if (MyModels.GetModelOnlyData(itemDefinition.Model).HavokBreakableShapes != null) { CreateBreakableShape(itemDefinition, ref itemData, ref hitWorldPosition, hitNormal, forceMultiplier); } else { ProfilerShort.Begin("Spawning tree"); // This is for SE when you hit a tree, it will create a floating object with the same model. In case it affects ME, it may be changed. Contact DusanA for it. Debug.Assert(MyPerGameSettings.Game == GameEnum.SE_GAME); MyPhysicalInventoryItem Item = new MyPhysicalInventoryItem() { Amount = 1, Content = new MyObjectBuilder_TreeObject() { SubtypeName = itemData.SubtypeId.ToString() } }; Vector3D pos = itemData.Transform.Position; Vector3D gravity = -MyGravityProviderSystem.CalculateNaturalGravityInPoint(pos); gravity.Normalize(); MyFloatingObjects.Spawn(Item, pos + gravity, MyUtils.GetRandomPerpendicularVector(ref gravity), gravity); ProfilerShort.End(); } } }
public override void DoDamage(float damage, int itemInstanceId, Vector3D position, Vector3 normal, MyStringHash type) { MyEnvironmentItemData itemData = m_itemsData[itemInstanceId]; MyDefinitionId id = new MyDefinitionId(Definition.ItemDefinitionType, itemData.SubtypeId); var itemDefinition = (MyTreeDefinition)MyDefinitionManager.Static.GetEnvironmentItemDefinition(id); int effectId; if (itemDefinition.CutEffect != null && MyParticlesLibrary.GetParticleEffectsID(itemDefinition.CutEffect, out effectId)) { MyParticleEffect effect; if (MyParticlesManager.TryCreateParticleEffect(effectId, out effect)) { effect.WorldMatrix = MatrixD.CreateWorld(position, Vector3.CalculatePerpendicularVector(normal), normal); effect.AutoDelete = true; } } if (!Sync.IsServer) { return; } MyCutTreeInfo cutTreeInfo = default(MyCutTreeInfo); int index = -1; for (int i = 0; i < m_cutTreeInfos.Count; ++i) { cutTreeInfo = m_cutTreeInfos[i]; if (itemInstanceId == cutTreeInfo.ItemInstanceId) { index = i; break; } } if (index == -1) { cutTreeInfo = new MyCutTreeInfo(); cutTreeInfo.ItemInstanceId = itemInstanceId; cutTreeInfo.MaxPoints = cutTreeInfo.HitPoints = itemDefinition.HitPoints; index = m_cutTreeInfos.Count; m_cutTreeInfos.Add(cutTreeInfo); } cutTreeInfo.LastHit = MySandboxGame.TotalGamePlayTimeInMilliseconds; cutTreeInfo.HitPoints -= damage; if (cutTreeInfo.Progress >= 1) { CutTree(itemInstanceId, position, normal, type == MyDamageType.Drill ? 1.0f : 4.0f); m_cutTreeInfos.RemoveAtFast(index); } else { m_cutTreeInfos[index] = cutTreeInfo; } return; }
private void CreateBreakableShape(MyEnvironmentItemDefinition itemDefinition, ref MyEnvironmentItemData itemData, ref Vector3D hitWorldPosition, Vector3 hitNormal, float forceMultiplier, string fallSound = "") { var breakableShape = VRage.Game.Models.MyModels.GetModelOnlyData(itemDefinition.Model).HavokBreakableShapes[0].Clone(); MatrixD world = itemData.Transform.TransformMatrix; breakableShape.SetMassRecursively(500); breakableShape.SetStrenghtRecursively(5000, 0.7f); breakableShape.GetChildren(m_childrenTmp); var test = VRage.Game.Models.MyModels.GetModelOnlyData(itemDefinition.Model).HavokBreakableShapes; Vector3 hitLocalPosition = Vector3D.Transform(hitWorldPosition, MatrixD.Normalize(MatrixD.Invert(world))); float cutLocalYPosition = (float)(hitWorldPosition.Y - (double)itemData.Transform.Position.Y); List <HkdShapeInstanceInfo> childrenBelow = new List <HkdShapeInstanceInfo>(); List <HkdShapeInstanceInfo> childrenAbove = new List <HkdShapeInstanceInfo>(); HkdShapeInstanceInfo? stumpInstanceInfo = null; foreach (var shapeInst in m_childrenTmp) { // The first child shape in the breakable shape should be the stump! if (stumpInstanceInfo == null || shapeInst.CoM.Y < stumpInstanceInfo.Value.CoM.Y) { stumpInstanceInfo = shapeInst; } if (shapeInst.CoM.Y > cutLocalYPosition) { childrenAbove.Add(shapeInst); } else { childrenBelow.Add(shapeInst); } } // Resolve stump - if we have 2 children bellow then move one to above list if (childrenBelow.Count == 2) { if (childrenBelow[0].CoM.Y < childrenBelow[1].CoM.Y && cutLocalYPosition < childrenBelow[1].CoM.Y + 1.25f) { childrenAbove.Insert(0, childrenBelow[1]); childrenBelow.RemoveAt(1); } else if (childrenBelow[0].CoM.Y > childrenBelow[1].CoM.Y && cutLocalYPosition < childrenBelow[0].CoM.Y + 1.25f) { childrenAbove.Insert(0, childrenBelow[0]); childrenBelow.RemoveAt(0); } } else if (childrenBelow.Count == 0) { if (childrenAbove.Remove(stumpInstanceInfo.Value)) { childrenBelow.Add(stumpInstanceInfo.Value); } else { Debug.Fail("Cannot remove shape instance from collection"); } } if (childrenBelow.Count > 0) { CreateFracturePiece(itemDefinition, breakableShape, world, hitNormal, childrenBelow, forceMultiplier, true); } if (childrenAbove.Count > 0) { CreateFracturePiece(itemDefinition, breakableShape, world, hitNormal, childrenAbove, forceMultiplier, false, fallSound); } m_childrenTmp.Clear(); }
private void CreateBreakableShape(MyEnvironmentItemDefinition itemDefinition, ref MyEnvironmentItemData itemData, ref Vector3D hitWorldPosition, Vector3 hitNormal, float forceMultiplier) { var breakableShape = MyModels.GetModelOnlyData(itemDefinition.Model).HavokBreakableShapes[0].Clone(); MatrixD world = itemData.Transform.TransformMatrix; breakableShape.SetMassRecursively(500); breakableShape.SetStrenghtRecursively(5000, 0.7f); breakableShape.GetChildren(m_childrenTmp); var test = MyModels.GetModelOnlyData(itemDefinition.Model).HavokBreakableShapes; Vector3 hitLocalPosition = Vector3D.Transform(hitWorldPosition, MatrixD.Normalize(MatrixD.Invert(world))); float cutLocalYPosition = (float)(hitWorldPosition.Y - (double)itemData.Transform.Position.Y); List<HkdShapeInstanceInfo> childrenBelow = new List<HkdShapeInstanceInfo>(); List<HkdShapeInstanceInfo> childrenAbove = new List<HkdShapeInstanceInfo>(); HkdShapeInstanceInfo? stumpInstanceInfo = null; foreach (var shapeInst in m_childrenTmp) { // The first child shape in the breakable shape should be the stump! if (stumpInstanceInfo == null || shapeInst.CoM.Y < stumpInstanceInfo.Value.CoM.Y) stumpInstanceInfo = shapeInst; if (shapeInst.CoM.Y > cutLocalYPosition) childrenAbove.Add(shapeInst); else childrenBelow.Add(shapeInst); } // Resolve stump - if we have 2 children bellow then move one to above list if (childrenBelow.Count == 2) { if (childrenBelow[0].CoM.Y < childrenBelow[1].CoM.Y && cutLocalYPosition < childrenBelow[1].CoM.Y + 1.25f) { childrenAbove.Insert(0, childrenBelow[1]); childrenBelow.RemoveAt(1); } else if (childrenBelow[0].CoM.Y > childrenBelow[1].CoM.Y && cutLocalYPosition < childrenBelow[0].CoM.Y + 1.25f) { childrenAbove.Insert(0, childrenBelow[0]); childrenBelow.RemoveAt(0); } } else if (childrenBelow.Count == 0) { if (childrenAbove.Remove(stumpInstanceInfo.Value)) childrenBelow.Add(stumpInstanceInfo.Value); else Debug.Fail("Cannot remove shape instance from collection"); } if (childrenBelow.Count > 0) CreateFracturePiece(itemDefinition, breakableShape, world, hitNormal, childrenBelow, forceMultiplier, true); if (childrenAbove.Count > 0) CreateFracturePiece(itemDefinition, breakableShape, world, hitNormal, childrenAbove, forceMultiplier, false); m_childrenTmp.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; }
/// <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; }
/// <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); }
private void CutTree(int itemInstanceId, Vector3D hitWorldPosition, Vector3 hitNormal, float forceMultiplier = 1.0f) { HkStaticCompoundShape shape = (HkStaticCompoundShape)Physics.RigidBody.GetShape(); int physicsInstanceId; if (m_localIdToPhysicsShapeInstanceId.TryGetValue(itemInstanceId, out physicsInstanceId)) { //Remove static tree MyEnvironmentItemData itemData = m_itemsData[itemInstanceId]; RemoveItem(itemInstanceId, physicsInstanceId, sync: true); //Create fractured tree MyDefinitionId id = new MyDefinitionId(Definition.ItemDefinitionType, itemData.SubtypeId); var itemDefinition = MyDefinitionManager.Static.GetEnvironmentItemDefinition(id); if (MyModels.GetModelOnlyData(itemDefinition.Model).HavokBreakableShapes != null) { var breakableShape = MyModels.GetModelOnlyData(itemDefinition.Model).HavokBreakableShapes[0].Clone(); MatrixD world = itemData.Transform.TransformMatrix; breakableShape.SetMassRecursively(500); breakableShape.SetStrenghtRecursively(5000, 0.7f); breakableShape.GetChildren(m_childrenTmp); var test = MyModels.GetModelOnlyData(itemDefinition.Model).HavokBreakableShapes; Vector3 hitLocalPosition = Vector3D.Transform(hitWorldPosition, MatrixD.Normalize(MatrixD.Invert(world))); float cutLocalYPosition = (float)(hitWorldPosition.Y - (double)itemData.Transform.Position.Y); List <HkdShapeInstanceInfo> childrenBelow = new List <HkdShapeInstanceInfo>(); List <HkdShapeInstanceInfo> childrenAbove = new List <HkdShapeInstanceInfo>(); HkdShapeInstanceInfo? stumpInstanceInfo = null; foreach (var shapeInst in m_childrenTmp) { // The first child shape in the breakable shape should be the stump! if (stumpInstanceInfo == null || shapeInst.CoM.Y < stumpInstanceInfo.Value.CoM.Y) { stumpInstanceInfo = shapeInst; } if (shapeInst.CoM.Y > cutLocalYPosition) { childrenAbove.Add(shapeInst); } else { childrenBelow.Add(shapeInst); } } // Resolve stump - if we have 2 children bellow then move one to above list if (childrenBelow.Count == 2) { if (childrenBelow[0].CoM.Y < childrenBelow[1].CoM.Y && cutLocalYPosition < childrenBelow[1].CoM.Y + 1.25f) { childrenAbove.Insert(0, childrenBelow[1]); childrenBelow.RemoveAt(1); } else if (childrenBelow[0].CoM.Y > childrenBelow[1].CoM.Y && cutLocalYPosition < childrenBelow[0].CoM.Y + 1.25f) { childrenAbove.Insert(0, childrenBelow[0]); childrenBelow.RemoveAt(0); } } else if (childrenBelow.Count == 0) { if (childrenAbove.Remove(stumpInstanceInfo.Value)) { childrenBelow.Add(stumpInstanceInfo.Value); } else { Debug.Fail("Cannot remove shape instance from collection"); } } if (childrenBelow.Count > 0) { CreateFracturePiece(itemDefinition, breakableShape, world, hitNormal, childrenBelow, forceMultiplier, true); } if (childrenAbove.Count > 0) { CreateFracturePiece(itemDefinition, breakableShape, world, hitNormal, childrenAbove, forceMultiplier, false); } m_childrenTmp.Clear(); } } }