public RawSceneObjectsList LoadScene()
        {
            using (Logger.EnterTimingStage("Loading all data from GTA"))
             {
            MessagesFilter? oldMessagesFilter = null;
            if (!Config.Instance.Loading.DetailedLogOutput)
            {
               oldMessagesFilter = Log.Instance.MessagesToOutput;
               Log.Instance.MessagesToOutput = MessagesFilter.Warning | MessagesFilter.Error;
            }
            try
            {
               string mainImgPath = Config.Instance.GTAFolderPath + "models/gta3.img";
               var loadedArchiveEntries = LoadMainImgArchive(mainImgPath);
               foreach (var item in loadedArchiveEntries)
                  loadedModels[item.Name.Substring(0, item.Name.Length - 4)] = new ModelEntry(item); // берём название модели без расширения .dff

               LoadDatFile("data/default.dat");
               LoadDatFile(GetVersionSpecificDatFile(gtaVersion));

               var sceneLowDetailed = new List<RawSceneObject>();
               var sceneHighDetailed = new List<RawSceneObject>();
               int missedIDEs = 0;

               PreprocessIpls();

               int shadowMinIdx = int.MaxValue;

               foreach (var obj in objPlacements)
               {
                  bool lowDetailedObj = obj.Name.StartsWith("lod");

                  string textureFolder = null;
                  var modelEntry = loadedModels[obj.Name];

                  if (modelEntry.Model == null)
                  {
                     if (objDefinitions.ContainsKey(obj.Id))
                     {
                        textureFolder = objDefinitions[obj.Id].TextureFolder;
                     }
                     else
                        ++missedIDEs;

                     var modelData = new DffLoader(modelEntry.FileProxy.GetData(), modelEntry.FileProxy.Name, textureFolder).Load();

                     // ignore object that has no texture coordinates
                     bool no_texture_coords = false;
                     foreach (var mesh in modelData.Meshes)
                        if (mesh.TextureCoords == null)
                        {
                           no_texture_coords = true;
                           break;
                        }
                     if (no_texture_coords)
                        continue;

                     modelEntry.Model = modelData;
                  }

                  // нам не нужны модели без значимой геометрии
                  if (modelEntry.Model.Meshes.Count == 0)
                     continue;

                  Matrix matrix = Matrix.CreateScale(obj.Scale) * Matrix.CreateFromQuaternion(obj.Rotation) * Matrix.CreateTranslation(obj.Position);

                  var objToAdd = new RawSceneObject(modelEntry.Model, matrix);
                  if (lowDetailedObj)
                     sceneLowDetailed.Add(objToAdd);
                  else
                  {
                     sceneHighDetailed.Add(objToAdd);
                     if (shadowMinIdx == int.MaxValue && isShadow(obj))
                        shadowMinIdx = sceneHighDetailed.Count - 1;
                  }
               }

               if (missedIDEs != 0)
                  Logger.Print(String.Format("Missed IDE(s): {0}", missedIDEs), MessageType.Warning);
               else
                  Logger.Print("No IDE was missed!");

               if (TexturesStorage.Instance.MissedTextures != 0)
                  Logger.Print(String.Format("Missed textures(s): {0}", TexturesStorage.Instance.MissedTextures), MessageType.Warning);
               else
                  Logger.Print("No texture was missed!");

               if (oldMessagesFilter != null)
                  Log.Instance.MessagesToOutput = oldMessagesFilter.Value;

               Logger.Print("Scene loaded!");
               Logger.PrintStatistic();
               Logger.Print(String.Format("Objects located on scene: {0} high-detailed, {1} low-detailed", sceneHighDetailed.Count, sceneLowDetailed.Count));
               Logger.Flush();

               var result = new RawSceneObjectsList(sceneHighDetailed, sceneLowDetailed);
               result.ShadowsStartIdx = shadowMinIdx;
               return result;

            }
            catch (Exception er)
            {
               Logger.Print("Failed to load scene! " + er, MessageType.Error);
               Logger.PrintStatistic();
               throw;
            }
            finally
            {
               if (oldMessagesFilter != null)
                  Log.Instance.MessagesToOutput = oldMessagesFilter.Value;
            }
             }
        }
        public RawSceneObjectsList LoadScene()
        {
            using (Logger.EnterTimingStage("Loading all data from GTA"))
            {
                MessagesFilter?oldMessagesFilter = null;
                if (!Config.Instance.Loading.DetailedLogOutput)
                {
                    oldMessagesFilter             = Log.Instance.MessagesToOutput;
                    Log.Instance.MessagesToOutput = MessagesFilter.Warning | MessagesFilter.Error;
                }
                try
                {
                    string mainImgPath          = Config.Instance.GTAFolderPath + "models/gta3.img";
                    var    loadedArchiveEntries = LoadMainImgArchive(mainImgPath);
                    foreach (var item in loadedArchiveEntries)
                    {
                        loadedModels[item.Name.Substring(0, item.Name.Length - 4)] = new ModelEntry(item); // берём название модели без расширения .dff
                    }
                    LoadDatFile("data/default.dat");
                    LoadDatFile(GetVersionSpecificDatFile(gtaVersion));

                    var sceneLowDetailed  = new List <RawSceneObject>();
                    var sceneHighDetailed = new List <RawSceneObject>();
                    int missedIDEs        = 0;

                    PreprocessIpls();

                    int shadowMinIdx = int.MaxValue;

                    foreach (var obj in objPlacements)
                    {
                        bool lowDetailedObj = obj.Name.StartsWith("lod");

                        string textureFolder = null;
                        var    modelEntry    = loadedModels[obj.Name];

                        if (modelEntry.Model == null)
                        {
                            if (objDefinitions.ContainsKey(obj.Id))
                            {
                                textureFolder = objDefinitions[obj.Id].TextureFolder;
                            }
                            else
                            {
                                ++missedIDEs;
                            }

                            var modelData = new DffLoader(modelEntry.FileProxy.GetData(), modelEntry.FileProxy.Name, textureFolder).Load();

                            // ignore object that has no texture coordinates
                            bool no_texture_coords = false;
                            foreach (var mesh in modelData.Meshes)
                            {
                                if (mesh.TextureCoords == null)
                                {
                                    no_texture_coords = true;
                                    break;
                                }
                            }
                            if (no_texture_coords)
                            {
                                continue;
                            }

                            modelEntry.Model = modelData;
                        }

                        // нам не нужны модели без значимой геометрии
                        if (modelEntry.Model.Meshes.Count == 0)
                        {
                            continue;
                        }

                        Matrix matrix = Matrix.CreateScale(obj.Scale) * Matrix.CreateFromQuaternion(obj.Rotation) * Matrix.CreateTranslation(obj.Position);

                        var objToAdd = new RawSceneObject(modelEntry.Model, matrix);
                        if (lowDetailedObj)
                        {
                            sceneLowDetailed.Add(objToAdd);
                        }
                        else
                        {
                            sceneHighDetailed.Add(objToAdd);
                            if (shadowMinIdx == int.MaxValue && isShadow(obj))
                            {
                                shadowMinIdx = sceneHighDetailed.Count - 1;
                            }
                        }
                    }

                    if (missedIDEs != 0)
                    {
                        Logger.Print(String.Format("Missed IDE(s): {0}", missedIDEs), MessageType.Warning);
                    }
                    else
                    {
                        Logger.Print("No IDE was missed!");
                    }

                    if (TexturesStorage.Instance.MissedTextures != 0)
                    {
                        Logger.Print(String.Format("Missed textures(s): {0}", TexturesStorage.Instance.MissedTextures), MessageType.Warning);
                    }
                    else
                    {
                        Logger.Print("No texture was missed!");
                    }

                    if (oldMessagesFilter != null)
                    {
                        Log.Instance.MessagesToOutput = oldMessagesFilter.Value;
                    }

                    Logger.Print("Scene loaded!");
                    Logger.PrintStatistic();
                    Logger.Print(String.Format("Objects located on scene: {0} high-detailed, {1} low-detailed", sceneHighDetailed.Count, sceneLowDetailed.Count));
                    Logger.Flush();

                    var result = new RawSceneObjectsList(sceneHighDetailed, sceneLowDetailed);
                    result.ShadowsStartIdx = shadowMinIdx;
                    return(result);
                }
                catch (Exception er)
                {
                    Logger.Print("Failed to load scene! " + er, MessageType.Error);
                    Logger.PrintStatistic();
                    throw;
                }
                finally
                {
                    if (oldMessagesFilter != null)
                    {
                        Log.Instance.MessagesToOutput = oldMessagesFilter.Value;
                    }
                }
            }
        }