public static MyPhysicalMaterialDefinition GetPhysicalMaterial(MyPhysicalModelDefinition modelDef, string physicalMaterial) { if (m_physicalMaterials == null) { m_physicalMaterials = new Dictionary <string, MyPhysicalMaterialDefinition>(); foreach (var physMat in MyDefinitionManager.Static.GetPhysicalMaterialDefinitions()) { m_physicalMaterials.Add(physMat.Id.SubtypeName, physMat); } m_physicalMaterials["Default"] = new MyPhysicalMaterialDefinition() { Density = 1920, HorisontalTransmissionMultiplier = 1, HorisontalFragility = 2, CollisionMultiplier = 1.4f, SupportMultiplier = 1.5f, }; } if (!string.IsNullOrEmpty(physicalMaterial)) { if (m_physicalMaterials.ContainsKey(physicalMaterial)) { return(m_physicalMaterials[physicalMaterial]); } else { string s = "ERROR: Physical material " + physicalMaterial + " does not exist!"; System.Diagnostics.Debug.Fail(s); MyLog.Default.WriteLine(s); } } //MyLog.Default.WriteLine("WARNING: " + modelDef.Id.SubtypeName + " has no physical material specified, trying to autodetect from name"); if (modelDef.Id.SubtypeName.Contains("Stone") && m_physicalMaterials.ContainsKey("Stone")) { return(m_physicalMaterials["Stone"]); } if (modelDef.Id.SubtypeName.Contains("Wood") && m_physicalMaterials.ContainsKey("Wood")) { return(m_physicalMaterials["Wood"]); } if (modelDef.Id.SubtypeName.Contains("Timber") && m_physicalMaterials.ContainsKey("Timber")) { return(m_physicalMaterials["Wood"]); } //MyLog.Default.WriteLine("WARNING: Unable to find proper physical material for " + modelDef.Id.SubtypeName + ", using Default"); return(m_physicalMaterials["Default"]); }
public short GetModelId(MyPhysicalModelDefinition def) { short id; if (!m_physicalModelToKey.TryGetValue(def, out id)) { id = (short)m_physicalModels.Count; m_physicalModelToKey.Add(def, id); m_physicalModels.Add(def); } return(id); }
public void AllocateForDefinition(string model, MyPhysicalModelDefinition definition, int count) { if (string.IsNullOrEmpty(model)) { return; } ProfilerShort.Begin("Clone"); var data = VRage.Game.Models.MyModels.GetModelOnlyData(model); if (data.HavokBreakableShapes == null) { MyDestructionData.Static.LoadModelDestruction(model, definition, data.BoundingBoxSize); } if (data.HavokBreakableShapes != null && data.HavokBreakableShapes.Length > 0) { ConcurrentQueue <HkdBreakableShape> queue; using (m_poolLock.AcquireExclusiveUsing()) { if (!m_pools.ContainsKey(definition.Id)) { m_pools[definition.Id] = new Dictionary <string, ConcurrentQueue <HkdBreakableShape> >(); } if (!m_pools[definition.Id].ContainsKey(model)) { m_pools[definition.Id][model] = new ConcurrentQueue <HkdBreakableShape>(); } queue = m_pools[definition.Id][model]; } for (int i = 0; i < count; i++) { var shape = data.HavokBreakableShapes[0].Clone(); queue.Enqueue(shape); if (i == 0) { var mp = new HkMassProperties(); shape.BuildMassProperties(ref mp); if (!mp.InertiaTensor.IsValid()) { MyLog.Default.WriteLine(string.Format("Block with wrong destruction! (q.isOk): {0}", definition.Model)); break; } } } } ProfilerShort.End(); }
public void AllocateForDefinition(string model, MyPhysicalModelDefinition definition, int count) { if (!string.IsNullOrEmpty(model)) { MyModel modelOnlyData = MyModels.GetModelOnlyData(model); if (modelOnlyData.HavokBreakableShapes == null) { MyDestructionData.Static.LoadModelDestruction(model, definition, modelOnlyData.BoundingBoxSize, true, false); } if ((modelOnlyData.HavokBreakableShapes != null) && (modelOnlyData.HavokBreakableShapes.Length != 0)) { ConcurrentQueue <HkdBreakableShape> queue; using (this.m_poolLock.AcquireExclusiveUsing()) { if (!this.m_pools.ContainsKey(definition.Id)) { this.m_pools[definition.Id] = new Dictionary <string, ConcurrentQueue <HkdBreakableShape> >(); } if (!this.m_pools[definition.Id].ContainsKey(model)) { this.m_pools[definition.Id][model] = new ConcurrentQueue <HkdBreakableShape>(); } queue = this.m_pools[definition.Id][model]; } for (int i = 0; i < count; i++) { HkdBreakableShape item = modelOnlyData.HavokBreakableShapes[0].Clone(); queue.Enqueue(item); if (i == 0) { HkMassProperties massProperties = new HkMassProperties(); item.BuildMassProperties(ref massProperties); if (!massProperties.InertiaTensor.IsValid()) { MyLog.Default.WriteLine($"Block with wrong destruction! (q.isOk): {definition.Model}"); return; } } } } } }
public void AllocateForDefinition(MyPhysicalModelDefinition definition, int count) { if (string.IsNullOrEmpty(definition.Model)) { return; } ProfilerShort.Begin("Clone"); var data = MyModels.GetModelOnlyData(definition.Model); if (MyFakes.LAZY_LOAD_DESTRUCTION && data.HavokBreakableShapes == null) { MyDestructionData.Static.LoadModelDestruction(definition, false, data.BoundingBoxSize); } if (data.HavokBreakableShapes != null && data.HavokBreakableShapes.Length > 0) { if (!m_pools.ContainsKey(definition.Id)) { m_pools[definition.Id] = new ConcurrentQueue <HkdBreakableShape>(); } var queue = m_pools[definition.Id]; for (int i = 0; i < count; i++) { var shape = data.HavokBreakableShapes[0].Clone(); queue.Enqueue(shape); if (i == 0) { var mp = new HkMassProperties(); shape.BuildMassProperties(ref mp); if (!mp.InertiaTensor.IsValid()) { MyLog.Default.WriteLine(string.Format("Block with wrong destruction! (q.isOk): {0}", definition.Model)); break; } } } } ProfilerShort.End(); }
public void Add(MyDefinitionId modelDef, int item) { ModelList itemsForModel; if (!m_modelPerItemDefinition.TryGetValue(modelDef, out itemsForModel)) { itemsForModel.Items = new List <int>(); if (modelDef.TypeId.IsNull) { itemsForModel.Model = -1; } else { MyPhysicalModelDefinition model = MyDefinitionManager.Static.GetDefinition <MyPhysicalModelDefinition>(modelDef); itemsForModel.Model = model != null?m_owner.GetModelId(model) : (short)-1; } m_modelPerItemDefinition[modelDef] = itemsForModel; } itemsForModel.Items.Add(item); }
public void LoadModelDestruction(MyPhysicalModelDefinition modelDef, bool dontCreateFracturePieces, Vector3 defaultSize, bool destructionRequired = true, bool useShapeVolume = false) { var model = MyModels.GetModelOnlyData(modelDef.Model); var material = modelDef.PhysicalMaterial; if (model != null) { bool forceCollisionsInsteadDestruction = false; //if (model.AssetName.Contains("StoneBattlementAdvancedStraightTop")) //{ //} model.LoadUV = true; HkdBreakableShape bShape; bool createPieceData = false; bool recalculateMass = false; bool registerShape = false; //TODO: Dynamic fracturing is workaround. We need to find the way how to serialize fractured model directly into hkt // and then load it from BreakableShapes. if (model.ModelFractures != null) { if (model.HavokCollisionShapes != null && model.HavokCollisionShapes.Length > 0) { CreateBreakableShapeFromCollisionShapes(model, defaultSize, modelDef); var physicsMesh = CreatePhysicsMesh(model); Storage.RegisterShapeWithGraphics(physicsMesh, model.HavokBreakableShapes[0], modelDef.Id.SubtypeName); string modPath = null; if (Path.IsPathRooted(model.AssetName)) { modPath = model.AssetName.Remove(model.AssetName.LastIndexOf("Models")); } FractureBreakableShape(model.HavokBreakableShapes[0], model.ModelFractures, modPath); recalculateMass = true; registerShape = true; createPieceData = true; } } else if (model.HavokDestructionData != null && !forceCollisionsInsteadDestruction) { try { //string dump = Storage.DumpDestructionData(model.HavokDestructionData); if (model.HavokBreakableShapes == null) //models are cached between sessions { model.HavokBreakableShapes = Storage.LoadDestructionDataFromBuffer(model.HavokDestructionData); createPieceData = true; recalculateMass = true; registerShape = true; } } catch { model.HavokBreakableShapes = null; } } model.HavokDestructionData = null; //we dont need to hold the byte data after loading shape model.HavokData = null; if (model.HavokBreakableShapes == null && destructionRequired) { MyLog.Default.WriteLine(model.AssetName + " does not have destruction data"); CreateBreakableShapeFromCollisionShapes(model, defaultSize, modelDef); recalculateMass = true; registerShape = true; if (MyFakes.SHOW_MISSING_DESTRUCTION && destructionRequired) { //Show missing destructions in pink VRageRender.MyRenderProxy.ChangeModelMaterial(model.AssetName, "Debug"); } } if (model.HavokBreakableShapes == null) { MyLog.Default.WriteLine(string.Format("Model {0} - Unable to load havok destruction data", model.AssetName), LoggingOptions.LOADING_MODELS); return; } System.Diagnostics.Debug.Assert(model.HavokBreakableShapes.Length > 0, "Incomplete destruction data"); bShape = model.HavokBreakableShapes[0]; //bShape.GetChildren(m_tmpChildrenList); //if (m_tmpChildrenList.Count == 0) // bShape.UserObject = (uint)HkdBreakableShape.Flags.FRACTURE_PIECE; if (dontCreateFracturePieces) { bShape.SetFlagRecursively(HkdBreakableShape.Flags.DONT_CREATE_FRACTURE_PIECE); } //m_tmpChildrenList.Clear(); if (registerShape) { bShape.AddReference(); Storage.RegisterShape( bShape, modelDef.Id.SubtypeName ); } // Necessary, otherwise materials on fractures would be missing VRageRender.MyRenderProxy.PreloadMaterials(model.AssetName); if (createPieceData) { CreatePieceData(model, bShape); } if (recalculateMass) { var volume = bShape.CalculateGeometryVolume(); if (volume <= 0 || useShapeVolume) { volume = bShape.Volume; } var realMass = volume * material.Density; if (bShape.Name == "House Half Timber Triangle") { } System.Diagnostics.Debug.Assert(realMass > 0, "Invalid mass data"); bShape.SetMassRecursively(MyDestructionHelper.MassToHavok(realMass)); } //Debug.Assert(CheckVolumeMassRec(bShape, 0.00001f, 0.01f), "Low volume or mass." + bShape.Name); DisableRefCountRec(bShape); if (MyFakes.LAZY_LOAD_DESTRUCTION) { BlockShapePool.AllocateForDefinition(modelDef, MyBlockShapePool.PREALLOCATE_COUNT); } } else { //No armor in ME! } }
void CreateBreakableShapeFromCollisionShapes(MyModel model, Vector3 defaultSize, MyPhysicalModelDefinition modelDef) { // Make box half edge length of the grid so fractured block is smaller than not fractured, also good for compounds HkShape shape; if (model.HavokCollisionShapes != null && model.HavokCollisionShapes.Length > 0) { if (model.HavokCollisionShapes.Length > 1) { shape = HkListShape.Create(model.HavokCollisionShapes, model.HavokCollisionShapes.Length, HkReferencePolicy.None); } else { shape = model.HavokCollisionShapes[0]; shape.AddReference(); } } else { //modelDef.Size * (modelDef.CubeSize == MyCubeSize.Large ? 2.5f : 0.25f) shape = new HkBoxShape(defaultSize * 0.5f, MyPerGameSettings.PhysicsConvexRadius); } var boxBreakable = new HkdBreakableShape(shape); boxBreakable.Name = model.AssetName; boxBreakable.SetMass(modelDef.Mass); model.HavokBreakableShapes = new HkdBreakableShape[] { boxBreakable }; shape.RemoveReference(); }