コード例 #1
0
        protected override void Save(string rawPath, Hashing.Hash128 hash, Dictionary <string, string> materialNameMapping, Dictionary <string, object> tags)
        {
            using (PoolManager.Get(out HashSet <string> shapeNames))
            {
                if (tags.TryGetValue(MyImporterConstants.TAG_HAVOK_DESTRUCTION, out var destructionBufferIn) ||
                    tags.TryGetValue(MyImporterConstants.TAG_HAVOK_COLLISION_GEOMETRY, out destructionBufferIn))
                {
                    using (var hkWorld = new HkWorld(true, 50000, float.MaxValue, false, 4, 0.6f))
                    {
                        hkWorld.MarkForWrite();
                        hkWorld.DestructionWorld = new HkdWorld(hkWorld);
                        hkWorld.UnmarkForWrite();
                        using (var destructionStorage = new HkDestructionStorage(hkWorld.DestructionWorld))
                        {
                            var result = destructionStorage.LoadDestructionDataFromBuffer((byte[])destructionBufferIn)[0];
                            CollectShapeNamesRecursive(result, shapeNames);
//                            RenameShapesRecursive(result, "_" + hash);
//                            var rawOutput = Path.GetTempFileName();
//                            destructionStorage.SaveDestructionData(result, rawOutput);
//                            var rawBytes = File.ReadAllBytes(rawOutput);
//                            FixupMaterialReferences(rawBytes, materialNameMapping);
//                            tags[MyImporterConstants.TAG_HAVOK_DESTRUCTION] = rawBytes;
//                            File.Delete(rawOutput);
                        }
                    }
                }

                if (tags.TryGetValue(MyImporterConstants.TAG_HAVOK_COLLISION_GEOMETRY, out var havokCollision))
                {
                    using (PoolManager.Get(out Dictionary <string, string> dict))
                    {
                        foreach (var kv in materialNameMapping)
                        {
                            dict[kv.Key] = kv.Value;
                        }
                        foreach (var name in shapeNames)
                        {
                            var hb = Hashing.Builder();
                            hb.Add(name);
                            hb.Add(hash);
                            dict[name] = hb.Build().ToLimitedString(name.Length);
                        }

                        FixupMaterialReferences((byte[])havokCollision, dict);
                    }
                }
            }

            var fullPath = Path.Combine(_exportContentRoot, rawPath);

            using (var writer = new BinaryWriter(File.Open(fullPath, FileMode.Create)))
                ModelExporter.ExportModelData(writer, tags);
        }
コード例 #2
0
        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!
            }
        }