Реалізація завантажувача файлів формату OBJ – РОЗРОБКА ІГОР ДЛЯ ОС ANDROID

Наш план дій буде таким – завантажити файл в память повністю і створити рядок для кожної його рядки Ми також створимо тимчасові масиви чисел з плаваючою точкою для всіх позицій вершин, координат текстур і нормалей, які ми збираємося завантажити Їх розмір дорівнює кількості рядків OBJ-файлу, помноженому на кількість компонент атрибута, – два для координат текстур або три для нормалей Завдяки цьому ми виділимо памяті більше, ніж необхідно, але це краще, ніж виділяти память для нових масивів всякий раз, коли їх знадобиться поповнити

Те ж саме ми зробимо для індексів, що визначають кожен трикутник Оскільки формат OBJ є індексованих, ми не можемо передати ці індекси безпосередньо в клас Vertices3

Причиною цього є той факт, що атрибути вершини можуть бути використані повторно кількома вершинами, тому складаються відносини один до багатьох, що не вирішується OpenGL ES Тому ми будемо використовувати неіндексований екземпляр класу Verti ces3 і просто дублювати вершини Такий підхід підійде для наших потреб

Подивимося, як ми можемо реалізувати все це Код цього класу міститься в лістингу 1112

Лістинг 1112 Клас ObjLoaderjava простий клас, призначений для завантаження підмножини формату 0BJ

Перше, що ми робимо, – відкриваємо в потоці InputStream файл з моделлю, що визначається параметром fi1е Потім в методі readLines (певному далі) ми зчитуємо всі рядки цього файлу Грунтуючись на кількості рядків, ми виділяємо память для масивів чисел з плаваючою точкою, які зберігатимуть компоненти осей х, у і z кожної нормалі вершин, а також і-і-координати текстур кожної вершини Оскільки ми не знаємо, скільки саме вершин ми побачимо у файлі, просто виділяємо більше памяті, ніж потрібно Кожен атрибут вершини зберігається в послідовних елементах трьох масивів Позиція перша ліченої вершини представлена елементами масиву vertices [0], vertices [1] і vertices [2] і т д Ми також відслідковуємо індекси при визначенні трикутників для кожного з трьох атрибутів вершини На додаток у нас є кілька лічильників для відстеження того, як багато всього ми вже завантажили

Далі у нас є цикл, яких проходить по всіх рядках файлів

Якщо поточна рядок є позицією вершини, ми зчитуємо її частини, розділені пробілами, такі як координати по осях х, у і г, і зберігаємо їх у масиві вершин

Ми робимо те ж саме для нормалей і координат текстур:

У цьому коді кожна вершина трикутника (названого тут face (ребро) через термінології формату OBJ) визначається трійкою індексів в масивах позиції вершин, координат текстур і нормалей Індекси координат текстур і нормалей можуть бути опущені, тому нам потрібно стежити за ними Індекси також можуть бути негативними, в цьому випадку нам доведеться додавати їх до кількості позицій / координат текстур / нормалей, завантажених раніше Цим займається метод getlndex

Як тільки ми завантажимо всі позиції вершин, нормалі і трикутники, ми можемо почати створювати масив чисел з плаваючою точкою, що містить вершини у форматі, який використовує екземпляр класу Vertices3 Кількість чисел з плаваючою точкою, необхідних для зберігання цих вершин, може бути з легкістю отримано як число завантажених трикутників, а також за допомогою інформації про те, чи задані нормалі і координати текстур

Щоб заповнити масив verts, ми просто проходимо по всіх трикутниках, отримуємо атрибути кожної вершини трикутника і поміщаємо їх в масив verts за шаблоном, який використовується екземпляром класу Verti ces3

Останнє, що ми робимо, – створюємо екземпляр класу Vertices3 і встановлюємо вершини

Інша частина методу присвячена обробці виключень і закриття потоку InputStream

Метод getlndex приймає один з індексів, заданих для атрибута вершини визначається трикутника, а також кількість раніше завантажених атрибутів, і повертає індекс, відповідний для посилання на атрибут, який знаходиться в одному з наших робочих масивів

Нарешті, розглянемо метод readlines, який просто зчитує кожен рядок файлу і повертає їх все як список рядків

Щоб завантажити OBJ-файл з ресурсу, ми можемо використовувати клас Ob j Loader наступним чином:

Досить прямолінійно після всієї цієї чехарди з індексами, чи не так Для отрисовки цього екземпляра класу Vertices3 нам необхідно знати, скільки він має вершин Розширимо клас Verti ces3 ще раз, додавши два методи, які повертають кількість вершин і кількість індексів, які визначені в обєкті в даний момент Код цих методів міститься в лістингу 1113

Лістинг 1113 Фрагменти класу Vertices3java, отримання кількості вершин та індексів

Для кількості індексів ми просто повертаємо кордон ShortBuffer, що зберігає індекси Для кількості вершин ми робимо те ж саме Однак, оскільки кордон повідомляється у вигляді кількості чисел з плаваючою точкою, визначених у буфері FloatBuffer, нам доведеться ділити його на розмір вершини

Оскільки ми зберігаємо це кількість байтів в параметрі vertexSize, ми ділимо цей член класу на 4

Використання класу OBJ Loader

Щоб продемонструвати роботу завантажувача файлів OBJ, я переписав останній приклад і створив новий тест, який називається ObjTest, а також екран ObjScreen Я скопіював весь код з попереднього прикладу і змінив тільки один рядок конструктора класу ObjScreen:

Тому замість використання методу createCube (який я прибрав) тепер ми безпосередньо завантажуємо модель з файлу з розширенням OBJ, який називається cubeobj У програмі Wings3D я створив копію куба, яку ми раніше створювали програмно в методі createCube Вона має ті ж позиції вершин, текстурні координати і нормалі, що і створена вручну версія Вас не повинно дивувати те, що результат роботи програми ObjTest виглядає точно так само, як і результат роботи Eul erCameraTest Тому я не буду приводити скріншот

Кілька зауважень щодо завантаження моделей

Для гри, завантажувач має велике значення, але він далеко не надійний Є кілька підводних каменів

Обробка рядків в ОС Android з визначення повільна OBJ – це формат, який використовує неформатований текст, тому він вимагає великих витрат часу на своє перетворення Це негативно вплине на час завантаження Ви можете обійти цю проблему, перетворюючи ваші OBJ-моделі в користувальницький бінарний формат Ви можете, наприклад, серіалізовать масив verts таким чином, що ми заповнюємо його в методі ObjLoader load О

Формат OBJ має набагато більше особливостей, ніж ми розглянули Якщо ви хочете розширити наш простий завантажувач, подивіться специфікацію формату в Інтернеті Додати нову функціональність має бути легко

OBJ-файл часто надається разом з файлом матеріалу Цей файл визначає кольору і текстури, які використовуються групами вершин, які описані в OBJ-файлі Нам не знадобиться ця функціональність, оскільки ми знаємо, яку текстуру використовувати для конкретного OBJ-файла Для створення більш надійного завантажувача вам буде потрібно заглянути в специфікацію файлів матеріалу

Джерело: Mario Zechner / Маріо Цехнер, «Програмування ігор під Android», пров Єгор Сидорович, Євген зазноби, Видавництво «Пітер»

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*