Пример #1
0
        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);
                    }
                }
            }
        }
Пример #2
0
        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);
        }
Пример #3
0
        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);
        }
Пример #4
0
        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);
        }
Пример #5
0
        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);
        }
Пример #6
0
        public bool GetItemWorldMatrix(int itemInstanceId, out MatrixD worldMatrix)
        {
            worldMatrix = MatrixD.Identity;

            MyEnvironmentItemData itemData = m_itemsData[itemInstanceId];

            worldMatrix = itemData.Transform.TransformMatrix;
            return(true);
        }
Пример #7
0
        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);
        }
Пример #8
0
        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);
        }
Пример #9
0
        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();
                }
            }
        }
Пример #10
0
        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;
        }
Пример #11
0
        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();
        }
Пример #12
0
        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();
        }
Пример #13
0
        /// <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;
        }
Пример #14
0
        /// <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;
        }
Пример #15
0
        /// <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);
        }
Пример #16
0
        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();
                }
            }
        }