Понедельник, 20.05.2024, 02:02


Главная
Регистрация
Вход
Мой сайт Приветствую Вас Гость | RSS  
Меню сайта

Мини-чат

Наш опрос
Оцените мой сайт
Всего ответов: 0

Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0

Форма входа

Главная » 2013 » Июнь » 15 » Написание пользовательского контент-импортера
00:56
 

Написание пользовательского контент-импортера

2-14. Написание пользовательского контент-импортера

by aklemen on 23.08.2012 at 11:46

Задача

Вы хотите загрузить файл пользовательского формата в ваш XNA проект через конвейер контента. Поскольку расширение и/или структура вашего файла будут отличаться от форматов файла, известных XNA, заданный по умолчанию конвейер контента XNA не знает, как импортировать и преобразовать ваш файл в полезный игровой объект.

Решение

Вы напишете пользовательский контент-импортер, способный считать файл с диска и форматировать ­полезные данные в объект, способный обрабатываться процессором контента. Поэтому, этот раздел предполагает, что вы уже знаете, как создать ваш собственный процессор контента. Вы можете прочитать введение в конвейер контента в разделе 3-9.

Этот раздел сосредотачивается только на пользовательском импортере. Contentlmporter должен читать данные с диска и форматировать их в объект. В этом разделе вы будете считывать из CSV файла значения, разделенные запятыми в два Vector3, и преобразовывать их в матрицу вида. Этот пример был выбран, потому что матрица вида нуждается в выполнении некоторых вычислений, и оболочка XNA идет с заданными по умолчанию TypeWriter и TypeReader способными к сериализации и десериализации объектов Matrix. Это позволяет в примере сосредоточить фокус на загрузке файла с диска, написании контент-импортера, и принятии данных пользовательским контент-процессором.

Взгляните на рисунок 5-27 для понимания этого примера. Пользовательский импортер будет считывать данные из файла CSV и создавать объект CSVImporterToProcessor, хранящий полезные данные, извлеченные из файла. Пользовательский CSVMatrixProcessor обработает данные в этом классе объекта CSVImporterToProcessor в объект Matrix. Далее, стандартные TypeWriter и TypeReader XNA для объекта Matrix будут заботиться о сериализации и десериализации­. Смотри разделы 4-15 и 4-16 для информации о создании ваших собственных TypeWriter и TypeReaders.

Поскольку и импортер и процессор вызываются во время компиляции, вы могли бы ­задаться вопросом, что хорошо бы разделить задачу обработки между импортером и процессором.

Например, не было бы намного проще только определить метод, который читает файл CSV и немедленно направляет эти данные в объект Matrix, вместо того, чтобы иметь два метода и промежуточный объект CSVMatrixProcessor?

Преимущество в данном случае в том, что вы можете многократно использовать процессор для нескольких импортеров ­(или наоборот). Например, XNA Framework идет с процессором, способным преобразовать объект NodeContent в объект ModelContent. Если вы импортируете модель из различных форматов из .x или .fbx, все, что вы должны сделать — написать импортер, который создает из вашего файла NodeContent, остальную работу выполнит стандартный ModelProcessor.

Рисунок 2-27. Определение пользовательского контент-импортера и его место в конвейере контента

Как это сделать

Вначале определим файл CSV, используя простой текстовый редактор. Это — то, на что похож мой файл CSV:

-5; 5; 8; 0; 2; 0;

Эти данные — позиция и цель назначения матрицы вида, которую вы создадите в этом разделе.

Промежуточный класс

Далее пройдите через контрольный список, представленный в разделе 3-9.Мой проект конвейера называется CSVToViewMatrixPipeline. Ничего не делайте на шаге 4 раздела 3-9; вы закодируете несколько дополнительных методов. В конце этого раздела вы можете найти полный код проекта конвейера контента.

Во-первых, вы нуждаетесь в объекте, который может использоваться, чтобы сохранить считанные данные с диска. Этот объект будет на выходе контент-импортера и на входе контен-процессора (который будет использовать его содержимое, чтобы создать матрицу вида). Добавьте пользовательский класс CSVImporterToProcessor, который может сохранить два Vector3:

public class CSVImporterToProcessor { private Vector3 position; private Vector3 target; public Vector3 Position { get { return position; } } public Vector3 Target { get { return target; } } public CSVImporterToProcessor(Vector3 position, Vector3 target) { this.position = position; this.target = target; } }

Этот класс способен сохранять два Vector3. Два метода get позволяют процессору обращаться к этим данным. Импортер будет должен предоставить все данные, вызывая метод конструктора.

Контент-импортер

Контент-импортер будет фактически читать данные из файла, так что убедитесь в этом, в начале вашего файла связавшись с пространством имен, содержащим их (это объяснялось в шаге 3 раздела 3-9, введении в конвейер контента):

using System.IO;

Вы готовы закодировать ваш пользовательский импортер. Добавьте следующий код:

[ContentImporter(".csv", DefaultProcessor = "CSVMatrixProcessor")] public class CSVImporter : ContentImporter<CSVImporterToProcessor> { public override CSVImporterToProcessor Import(string filename,ContentlmporterContext context) { } }

Атрибут указывает, что этот класс — импортер контента, способный к обработке .csv файлов и что по умолчанию ее вывод должен обработать CSVHeightMapProcessor (который вы создадите через мгновение). В следующей строке вы определяете, что этот импортер генерирует объект CSVImporterToProcessor.

Во время компиляции, импортер получает имя .csv файла, который будет импортирован, и должен преобразовать его в объект CSVImporterToProcessor. Вначале открывается файл и ­считывается первая строка, как сделано в начале нижеприведенного кода. Для отделения значений между ; вы используете простой метод Strip, который в этом случае возвращает массив трех строк из каждой строки, сохраняя числа для нашей позиции камеры. Следующие три строки ­конвертируют эти строки в числа с плавающей точкой, которые используются для создания позиции в Vector3.

StreamReader file = new StreamReader(filename); string line = file.Readline(); string[] lineData = line.Split(';'); float x = float.Parse(lineData[0]); float у = float.Parse(lineData[l]); float z = float.Parse(lineData[2]); Vector3 position = new Vector3(x,y,z);

Вы считываете вторую строку из файла и конвертируете его в Vector3 таким же способом:

line = file.Readline(); lineData = line.Split(';'); x = float.Parse(lineData[0]); у = float.Parse(lineData[1]); z = float.Parse(lineData[2]); Vector3 target = new Vector3(x,y,z);

Теперь, у вас есть все данные для создания объекта CSVImporterToProcessor:

CSVImporterToProcessor finalData = new CSVImporterToProcessor(position, target); return finalData;

Этот объект отправит процессору данные для обработки. Очевидно, процессор должен быть способен принять на вход объект CSVImporterToProcessor.

Получение данных в контент-процессоре

Поскольку класс CSVImporterToProcessor — пользовательский класс, вы должны создать пользовательский процессор. Этот типовой процессор обработает объект CSVImporterToProcessor в объект Matrix. См. первые разделы этой главы для информации о том, как создать матрицу вида, основанную на позиции и цели назначения камеры:

[ContentProcessor] public class CSVMatrixProcessor : ContentProcessor<CSVImporterToProcessor, Matrix> { public override Matrix Process(CSVImporterToProcessor input,ContentProcessorContext context) { Vector3 up = new Vector3(0, 1, 0); Vector3 forward = input.Target - input.Position; Vector3 right = Vector3.Cross(forward, up); up = Vector3.Cross(right, forward); Matrix viewMatrix = Matrix.Createl_ookAt(input.Position, input.Target, up); } return viewMatrix; }

Вы указываете, что этот процессор способен преобразовать объект CSVImporterToProcessor в объект Matrix. Позиция и цель назначения в объекте CSVImporterToProcessor используются, чтобы создать матрицу вида. XNA по умолчанию знает, как сериализовать/десериализовать объект Matrix в в\из бинарный файл и загрузить результирующий объект Matrix в ваш игровой проект XNA, таким образом вы не должны кодировать пользовательские TypeWriter и TypeReader.

Использование

Когда вы убедитесь, что выполнили все девять шагов из раздела 3-9, вы можете импортировать .csv файлы в ваш проект. Когда вы выбираете такой импортированный .csv файл в своем Solution Explorer, обратите внимание в окне Properties, что файл будет импортирован вашим CSVImporter, как показано на рисунке 2-28. Кроме того, потому что вы указали заданный по умолчанию процессор, им выбирается CSVMatrixProcessor.

Рисунок 2-28. Выбор контент-импортера и контент-процессора

Как только.csv файл был импортирован, все, что вы должны сделать для загрузки матрицы вида из .csv файла — только добавить одну строку программы:

protected override void LoadContent() { viewMatrix = Content.Load<Matrix>("camerasettings"); }

Код

Так как весь конвейер контента очень короткий, я приведу его здесь в одной части. Первый блок связывается с необходимыми пространствами имен. Первый класс в пространстве имен — класс CSVImporterToProcessor, который необходим для сохранения всех необходимых данных от импортера к процессору. Затем непосредственно класс ContentImporter, который способен считывать.csv файл и сохранять полезные данные в объекте CSVImporterToProcessor. Последний блок – контента-процессор, способный создать матрицу вида, основанную на содержимом объекта CSVImporterToProcessor. Так как XNA идет с TypeWriter и TypeReader способных обработать объект Matrix, то это все что нужно для полностью функционального конвейера контента. Если ваш процессор создает объект пользовательского класса, см. разделы 4-15 и 4-16 для информации о том, как создать ваши собственные TypeWriter и TypeReader.

using System; using System.Collections.Generic; using System.Linq; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Content.Pipeline; using Microsoft.Xna.Framework.Content.Pipeline.Graphics; using Microsoft.Xna.Framework.Content.Pipeline.Processors; using System.IO; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler; namespace CVSToViewMatrixPipeline { public class CSVImporterToProcessor { private Vector3 position; private Vector3 target; public Vector3 Position { get { return position; } } public Vector3 Target { get { return target; } } public CSVImporterToProcessor(Vector3 position, Vector3 target) { this.position = position; this.target = target; } } [ContentImporter(".csv", DefaultProcessor = "CSVMatrixProcessor")] public class CSVImporter : ContentImporter<CSVImporterToProcessor> { public override CSVImporterToProcessor Import(string filename,ContentlmporterContext context) { StreamReader file = new StreamReader(filename); string line = file.ReadLine(); string[] lineData = line.Split(';'); float x = float.Parse(lineData[0]); float у = float.Parse(lineData[l]); float z = float.Parse(lineData[2]); Vector3 position = new Vector3(x,y,z); line = file.ReadLine(); lineData = line.Split(';'); x = float.Parse(lineData[0]); у = float.Parse(lineData[l]); z = float.Parse(lineData[2]); Vector3 target = new Vector3(x,y,z); CSVImporterToProcessor finalData = new CSVImporterToProcessor(position, target); return finalData; } } [ContentProcessor] public class CSVMatrixProcessor : ContentProcessor<CSVImporterToProcessor, Matrix> { public override Matrix Process(CSVImporterToProcessor input, ContentProcessorContext context) { Vector3 up = new Vector3(0, 1, 0); Vector3 forward = input.Target - input.Position; Vector3 right = Vector3.Cross(forward, up); up = Vector3.Cross(right, forward); Matrix viewMatrix = Matrix.CreateLookAt(input.Position, input.Target, up); return viewMatrix; } }

(133)

Просмотров: 287 | Добавил: oweemeas | Рейтинг: 0.0/0
Всего комментариев: 0
Поиск

Календарь
«  Июнь 2013  »
ПнВтСрЧтПтСбВс
     12
3456789
10111213141516
17181920212223
24252627282930

Архив записей

Друзья сайта
  • Официальный блог
  • Сообщество uCoz
  • FAQ по системе
  • Инструкции для uCoz

  • Copyright MyCorp © 2024Конструктор сайтов - uCoz