/// <summary> /// Initialize predefined models<para/> /// Инициализация предзаданных моделей /// </summary> public static void Init() { // Load DAT-defined texture dictionaries // Загрузка предопределенных архивов текстур foreach (string DFF in FileManager.ModelFiles) { string name = Path.GetFileNameWithoutExtension(DFF).ToLower(); string path = PathManager.GetAbsolute(DFF); ModelFile f = new ModelFile(path, true); CachedFiles.TryAdd(name, f); Model m = new Model(f, true, true); Cached.TryAdd(name, m); } // Starting ModelFile thread // Запуск потока чтения ModelFile fileReaderThread = new Thread(FileLoaderProcess); fileReaderThread.IsBackground = true; fileReaderThread.Priority = ThreadPriority.BelowNormal; fileReaderThread.Start(); // Starting model builder thread // Запуск потока постройки Model modelBuilderThread = new Thread(ModelBuilderProcess); modelBuilderThread.IsBackground = true; modelBuilderThread.Priority = ThreadPriority.BelowNormal; modelBuilderThread.Start(); }
/// <summary> /// Check if currently background thread is processing this model<para/> /// Проверка, обрабатывается ли указанная модель /// </summary> /// <param name="model">Model to check<para/>Модель для проверки</param> /// <returns>True if model is processing<para/>True если модель обрабатывается</returns> public static bool IsProcessing(Model model) { return ModelProcessQueue.Contains(model) || ReadyModelQueue.Contains(model); }
static void RenderBonesRecursively(Model.Branch[] branches) { foreach (Model.Branch b in branches) { if (b.Parent!=null) { rend.Primitives.Add(new Graphics.Renderers.DebugRenderer.Line() { Start = b.Matrix.ExtractTranslation() * 10f, End = b.Parent.Matrix.ExtractTranslation() * 10f, Color = new Vector3(1f, 1f, 0f), LineSize = 3f }); } if (b.SubMeshes.Length > 0) { re.SubMesh = b.SubMeshes[0]; re.SubmeshMatrix = b.Matrix; re.BaseMatrix = Matrix4.CreateScale(10f); re.Textures = manTex; } if (b.Children!=null) { RenderBonesRecursively(b.Children); } } }
/// <summary> /// Process mesh internals<para/> /// Обработка данных меша /// </summary> public void Process(bool needed) { if (needed) { if (GroupModel != null) { if (GroupTextures != null) { if (GroupModel.State == Model.ReadyState.Complete && GroupTextures.State == TextureDictionary.ReadyState.Complete) { // Surface is ready to render // Поверхность готова к отрисовке Ready = true; Model.SubMesh[] subs = GroupModel.GetAllSubMeshes(); Renderers = new StaticRenderer[subs.Length]; Coords.Position = Coords.Position; for (int i = 0; i < Renderers.Length; i++) { Renderers[i] = new StaticRenderer() { BaseMatrix = Coords.Matrix, SubmeshMatrix = subs[i].Parent.Matrix, SubMesh = subs[i], Textures = GroupTextures, Fading = false, FadingDelta = 1 }; } } else { // Check for model state // Проверка состояния модели if (GroupModel.State != Model.ReadyState.Complete) { if (GroupModel.File.State == Files.RenderWareFile.LoadState.Complete) { if (!ModelManager.IsProcessing(GroupModel)) { ModelManager.ModelProcessQueue.Enqueue(GroupModel); } } } // Check for texture dictionary state // Проверка состояния архива текстур if (GroupTextures.State != TextureDictionary.ReadyState.Complete) { if (GroupTextures.File.State == Files.RenderWareFile.LoadState.Complete) { if (!TextureManager.IsProcessing(GroupTextures)) { TextureManager.TextureProcessQueue.Enqueue(GroupTextures); } } } } } else { // Texture not found - get it // Текстура не найдена - получаем её string tname = ObjectManager.Definitions[Definition.ID].TexDictionary; if (TextureManager.Cached.ContainsKey(tname)) { GroupTextures = TextureManager.Cached[tname]; } else { TextureFile tf = null; if (TextureManager.CachedFiles.ContainsKey(tname)) { tf = TextureManager.CachedFiles[tname]; } else { tf = new TextureFile(ArchiveManager.Get(tname + ".txd"), false); TextureManager.CachedFiles.TryAdd(tname, tf); TextureManager.TextureFileProcessQueue.Enqueue(tf); } GroupTextures = new TextureDictionary(tf); TextureManager.Cached.TryAdd(tname, GroupTextures); } GroupTextures.UseCount++; } } else { // Model not found - get it // Модель не найдена - получаем её string mname = ObjectManager.Definitions[Definition.ID].ModelName; if (ModelManager.Cached.ContainsKey(mname)) { GroupModel = ModelManager.Cached[mname]; } else { ModelFile mf = null; if (ModelManager.CachedFiles.ContainsKey(mname)) { mf = ModelManager.CachedFiles[mname]; } else { mf = new ModelFile(ArchiveManager.Get(mname + ".dff"), false); ModelManager.CachedFiles.TryAdd(mname, mf); ModelManager.ModelFileProcessQueue.Enqueue(mf); } GroupModel = new Model(mf); ModelManager.Cached.TryAdd(mname, GroupModel); } GroupModel.UseCount++; } } else { // Cleaning all the usings // Очистка использований if (GroupModel != null) { if (!GroupModel.Important) { GroupModel.UseCount--; } GroupModel = null; } if (GroupTextures != null) { if (!GroupTextures.Important) { GroupTextures.UseCount--; } GroupTextures = null; } if (Renderers!=null) { Renderers = null; } Ready = false; } }
/// <summary> /// Release memory used by this mesh<para/> /// Очистка памяти, используемой этим мешем /// </summary> public void Release() { // Removing surfaces // Удаляем поверхности foreach (Surface s in Surfaces) { s.IndexData = null; s.Material = null; if (s.IndexBuffer != 0) GL.DeleteBuffer(s.IndexBuffer); } geometry = null; Parent = null; ParentModel = null; // Removing buffers // Удаляем буфферы vertexData = null; normalData = null; colorData = null; texCoord1Data = null; texCoord2Data = null; if (vertexBuffer != 0) GL.DeleteBuffer(vertexBuffer); if (normalBuffer != 0) GL.DeleteBuffer(normalBuffer); if (colorBuffer != 0) GL.DeleteBuffer(colorBuffer); if (tex1Buffer != 0) GL.DeleteBuffer(tex1Buffer); if (tex2Buffer != 0) GL.DeleteBuffer(tex2Buffer); }
/// <summary> /// Create submesh from ModelFile's Geometry entry<para/> /// Создание сабмеша из данных Geometry /// </summary> /// <param name="g">Loaded Geometry<para/>Загруженая Geometry</param> public SubMesh(Branch parent, Model model, ModelFile.Geometry g) { // Setting up the fields // Настройка полей State = ReadyState.Empty; Parent = parent; ParentModel = model; geometry = g; }
/// <summary> /// Creating branch for existing model<para/> /// Создание ветки для существующей модели /// </summary> /// <param name="model">Parent model<para/>Модель-родитель</param> /// <param name="parent">Parent branch<para/>Родительский бранч</param> /// <param name="branchIndex">Branch index in ModelFile<para/>Индекс в файле модели</param> public Branch(Model model, Branch parent, int branchIndex) { // Setting up special data // Установка спецданных ModelFile.Frame f = model.File.Frames[branchIndex]; Position = new Vector3(f.Position[0], f.Position[2], f.Position[1]); Quaternion q = Quaternion.FromMatrix( new Matrix3( f.Rotation[0], f.Rotation[1], f.Rotation[2], f.Rotation[3], f.Rotation[4], f.Rotation[5], f.Rotation[6], f.Rotation[7], f.Rotation[8] ) ); Angles = new Quaternion(-q.X, -q.Z, -q.Y, -q.W); Scale = 1f; ParentModel = model; Parent = parent; Name = f.Name; // Hack to rebuild matrix // Хак для перестройки матрицы needNewMatrix = true; mat = Matrix; // Analyze model's geometries for data // Анализируем геометрию модели для создание сурфейсов List<SubMesh> lm = new List<SubMesh>(); foreach (ModelFile.Geometry g in model.File.Surfaces) { if (g.Frame == branchIndex) { lm.Add(new SubMesh(this, model, g) { }); } } SubMeshes = lm.ToArray(); // Analyze sub-branches // Выборка дочерних веток List<Branch> ch = new List<Branch>(); for (int i = 0; i < model.File.Frames.Length; i++) { ModelFile.Frame fr = model.File.Frames[i]; if (fr.Parent == branchIndex) { ch.Add(new Branch(model, this, i) { }); } } Children = ch.ToArray(); }