Как отключить уведомления на Android?
Устанавливая каждое приложение, владелец смартфона соглашается с запросами на доступ к определенным данным и возможностям...
Этот урок показывает способ загрузки моделей из файлов.obj
Формат obj - это текстовые файлы, содержащие очень мало данных о модели. Но благодаря своей
простоте эти файлы может импортировать/экспортировать практически любой соответствующий софт.
Код урока взят из урока "загрузка текстур".
Минус формата.obj - он не хранит информации о материалах, так что мне пришлось придумать другой способ.
Я бы не стал использовать этот формат для демки или игры, но полезно уметь с ним обращатся, так как
он очень прост и популярен. Вообще, надо было написать этот урок раньше загрузки 3sd...
В этом уроке мы будем использовать STL vector. Что это такое я подробно описал в уроке "загрузка.3ds".
Вот небольшое описание формата OBJ. Каждая программа, экспортирующая и импортирующая этот формат,
делает это по-своему. Некоторые сохраняют нормали, некоторые - имена обьектов, и так далее.
Данные вы читаете на основе первого символа в строке.
"v" - эта линия содержит вершину (x y z)
// пример: v -1 -1 0
Прочитав все такие линии, вы получите геометрию обьекта.
"vt" - текстурные координаты обьекта (U V)
// пример: vt .99998 .99936
"f" - эта линия содержит индексы вершин для массива полигонов.
Если есть UV координаты, она содержит также и их индексы.
// пример: (Только вершины): f 1 2 3
// пример: (Вершины и текстуры): f 1/1 2/2 3/3
Теперь напишем класс, загружающий.obj-файл.
Новый файл: obj.h
:
#ifndef _OBJ_H
#define _OBJ_H
#include "main.h"
// Класс, загружающий файл формата OBJ
public:
// Вы будете вызывать только эту функцию. Просто передаёте структуру
// модели для сохранения данных, и имя файла для загрузки.
bool ImportObj(t3DModel *
pModel,
char
*
strFileName)
;
// Главный загружающий цикл, вызывающийся из ImportObj()
void
ReadObjFile(t3DModel *
pModel)
;
// Вызывается в ReadObjFile() если линия начинается с "v"
void
ReadVertexInfo()
;
// Вызывается в ReadObjFile() если линия начинается с "f"
void
ReadFaceInfo()
;
// Вызывается после загрузки информации полигонов
void
FillInObjectInfo(t3DModel *
pModel)
;
// Вычисление нормалей. Это не обязятельно, но очень желательно.
void
ComputeNormals(t3DModel *
pModel)
;
// Так как.obj файлы не хранят имен текстур и информации о материалах, мы создадим
// функцию, устанавливающую их вручную. materialID - индекс для массива pMaterial нашей модели.
void
SetObjectMaterial(t3DModel *
pModel,
int
whichObject,
int
materialID)
;
// Чтобы проще присваивать материал к.obj обьекту, создадим для этого функцию.
// Передаём в неё модель, имя материала, имя файла текстуры и цвет RGB.
// Если нам нужен только цвет, передаём NULL для strFile.
void
AddMaterial(t3DModel *
pModel,
char
*
strName,
char
*
strFile,
int
r =
255
,
int
g =
255
,
int
b =
255
)
;
private:
// Указатель на файл
FILE *
m_FilePointer;
// STL vector, содержащий список вершин
vector<
CVector3>
m_pVertices;
// STL vector, содержащий список полигонов
vector<
tFace>
m_pFaces;
// STL vector, содержащий список UV координат
vector<
CVector2>
m_pTextureCoords;
// Говорит нам, имеет ли обьект текстурные координаты
bool m_bObjectHasUV;
// Говорит нам, что мы только что прочитали данные полигонов, чтобы мы могли читать несколько обьектов
bool m_bJustReadAFace;
}
;
#endif
Файл obj.cpp
:
#include "main.h"
#include "obj.h"
///// Функция загружает файл.obj в указанную переменную из указанного имени файла
///////////////////////////////// IMPORT OBJ \\\\\\\\\\\\\\\\*
Bool CLoadObj::ImportObj(t3DModel *pModel, char *strFileName)
{
char strMessage = {0}; // Будет использоваться для сообщения об ошибке
// Убедимся, что переданы не пустые модель и имя файла
if(!pModel || !strFileName) return false;
// Открываем указанный файл для чтения
m_FilePointer = fopen(strFileName, "r");
// Убедимся, что файл правильно открыт
if(!m_FilePointer) {
// Сформируем сообщение об ошибке
sprintf(strMessage, "Unable to find or open the file: %s", strFileName);
MessageBox(NULL, strMessage, "Error", MB_OK);
return false;
}
// Теперь, имея открытый файл, считываем информацию
ReadObjFile(pModel);
// Прочитав всю информацию, вычисляем вершинные нормали
ComputeNormals(pModel);
// Закрываем файл
fclose(m_FilePointer);
// И возвращаем true
return true;
}
///// Эта функция - главный цикл чтения файла.obj
///////////////////////////////// READ OBJ FILE \\\\\\\\\\\\\\\\*
Void CLoadObj::ReadObjFile(t3DModel *pModel)
{
char strLine = {0};
char ch = 0;
While(!feof(m_FilePointer))
{
float x = 0.0f, y = 0.0f, z = 0.0f;
// Читаем первый символ текущей строки файла
ch = fgetc(m_FilePointer);
Switch(ch)
{
case "v": // Проверяем, не "v" ли это (может быть вершина/нормаль/текст. коорд.)
// Если мы только что читали информацию о полигоне, а сейчас читаем вершину,
// значит мы перешли к следующему обьекту, и нужно сохранить данные предыдущего.
if(m_bJustReadAFace) {
// Сохраняем данные последнего обьекта в структуру модели
FillInObjectInfo(pModel);
}
// Расшифровываем всю текущую линию
ReadVertexInfo();
break;
Case "f": // Если первый символ -"f", эта строка описывает полигон
// Если прочитан символ новой строки - это пустая строка, ничего не делаем.
break;
Default:
// Если что-то неизвестное, просто читаем эту строку в "мусор", чтобы перейти
// к следующей - нам она не нужна.
break;
}
}
// Теперь сохраняем последний прочитанный обьект
FillInObjectInfo(pModel);
}
///// Эта функция читает информацию о вершинах ("v" вершина: "vt" UVCoord)
///////////////////////////////// READ VERTEX INFO \\\\\\\\\\\\\\\\*
Void CLoadObj::ReadVertexInfo()
{
CVector3 vNewVertex = {0};
CVector2 vNewTexCoord = {0};
char strLine = {0};
char ch = 0;
// Читаем второй сисвол строки, чтобы увидеть, что содержит строка: вершины/нормали/UV
ch = fgetc(m_FilePointer);
// Читаем остальную линию, чтобы перейти к следующей
fgets(strLine, 100, m_FilePointer);
// Добавляем новую вершину в список
m_pVertices.push_back(vNewVertex);
}
else if(ch == "t") // Если второй символ - "t", строка содержит UV координаты ("vt")
{
// Читаем текстурные координаты. Формат: "vt u v"
fscanf(m_FilePointer, "%f %f", &vNewTexCoord.x, &vNewTexCoord.y);
// Читаем оставшуюся линию, чтобы перейти к следующей
fgets(strLine, 100, m_FilePointer);
// Вносим новые текстурные координаты в список
m_pTextureCoords.push_back(vNewTexCoord);
// Активируем флаг, сообщающий, что обьект имеет текстурные координаты.
// Теперь мы знаем, что строки полигонов будут содержать индексы не только
// вершин, но и текст. координат ("f 1/1 2/2 3/3")
m_bObjectHasUV = true;
}
else // Иначе это, видимо, нормаль, и нам она не нужна ("vn")
{
// Мы рассчитываем собственные нормали, так что пропустим строку
fgets(strLine, 100, m_FilePointer);
}
}
///// Читает информацию полигона ("f")
///////////////////////////////// READ FACE INFO \\\\\\\\\\\\\\\\*
Void CLoadObj::ReadFaceInfo()
{
tFace newFace = {0};
char strLine = {0};
// Функция читает информацию о полигонах обьекта.
// Эта информация - 3д точки, составляющие полигон, и UV координаты,
// если на обьект наложена текстура.
// Если обьект имеет текстурные координаты, формат строки будет
// такой: "f v1/uv1 v2/uv2 v3/uv3"
// Иначе такой: "f v1 v2 v3"
// Внимание! Всегда убеждайтесь, что вычитаете 1 из индексов, так как
// массивы в c++ начинаются с 0, а индексы в.obj начинаются с 1.
// Проверяем, имеет ли обьект текстурные координаты
if(m_bObjectHasUV)
{
// Читаем индексы вершин и текстурных координат.
fscanf(m_FilePointer, "%d/%d %d/%d %d/%d", &newFace.vertIndex, &newFace.coordIndex,
&newFace.vertIndex, &newFace.coordIndex,
&newFace.vertIndex, &newFace.coordIndex);
}
else // если обьект НЕ содержит текстурных координат
{
// Читаем только индексы вершин
fscanf(m_FilePointer, "%d %d %d", &newFace.vertIndex,
&newFace.vertIndex,
&newFace.vertIndex);
}
// Читаем линию до конца, чтобы перейти к следующей
fgets(strLine, 100, m_FilePointer);
// Добавляем новый полигон в список
m_pFaces.push_back(newFace);
// Устанавливаем этот флаг в TRUE, чтобы знать, что только что читали полигон. Если
// после этого читается вершина - значит, мы перешли к следующему обьекту и нужно
// сохранить этот.
m_bJustReadAFace = true;
Если появилась ситуация, в которой Вы не можете открыть файл OBJ на своем компьютере - причин может быть несколько. Первой и одновременно самой важной (встречается чаще всего) является отсутствие соответствующей аппликации обслуживающей OBJ среди установленных на Вашем компьютере.
Самым простым способом решения этой проблемы является нахождение и скачивание соответствующей аппликации. Первая часть задания, уже выполнена, - программы для обслуживания файла OBJ Вы найдете ниже. Теперь достаточно скачать и установить соответствующую аппликацию.
В дальнейшей части этой страницы Вы найдете другие возможные причины, вызывающие проблемы с файлами OBJ.
Отсутствие возможности открытия и работы с файлом OBJ, совсем не должен значить, что мы не имеем установленного на своем компьютере соответствующего программного обеспечения. Могут выступать другие проблемы, которые также блокируют нам возможность работы с файлом 3D Object Format. Ниже находится список возможных проблем.
Если Вы уверены, что все перечисленные поводы отсутствуют в Вашем случае (или были уже исключены), файл OBJ должен сотрудничать с Вашими программами без каких либо проблем. Если проблема с файлом OBJ все-таки не решена, это может значить, что в этом случае появилась другая, редкая проблема с файлом OBJ. В таком случае остается только помощь специалиста.
Файлы с расширением.obj содержат файлы 3D объектов, созданных с помощью компьютерной программы для рисования. Подобные файлы могут содержать карты текстур, 3D координаты и другие сведения о 3D-объектах.
Формат OBJ применяется в самых разнообразных приложениях, разрабатывающих 3D-графику, в частности в Microsoft Visual Studio и CADRazor.
Помимо этого, суффикс.оbj используется при работе с файлами объектов компьютерной науки. Такие файлы содержат набор последовательностей - инструкции, позволяющие хост-компьютеру правильно выполнять поставленные задачи. В данном случае файлы OBJ могут сопровождаться соответствующими файлами метаданных.
Файлы OBJ создаются также несколькими компиляторами для Windows, например. C и C++ . В результате обработки исходного кода файла появляется файл с расширением.obj. Когда все файлы исходного кода скомпилированны в файлы OBJ, они связываются друг с другом для формирования файла EXE или DLL.
Расширение файла OBJ известен как Wavefront 3D Object File, который был разработан Wavefront Technologies. Это формат файла, используемый для трехмерного объекта, содержащего 3D-координаты (полигон линии и точки), текстурные карты, а также другую информацию об объекте. Она содержит стандартный 3D формат изображения, который может быть экспортирован и открыл несколько 3D-программ для редактирования изображений. Объектные файлы могут быть в формате ASCII (.obj) или двоичный формат (.mod), однако не содержит определения цвета для граней. Из-за их формата, они читаемым человеком. Он поддерживает как полигональные объекты свободной формы и объекты. Многоугольная геометрия использует точки, линии, и лица для определения объектов, в то время как в свободной форме геометрии используются кривые и поверхности. Файлы в формате OBJ можно открыть с помощью Autodesk Maya 2013, Blender и MeshLab в Microsoft Windows, Mac OS и Linux платформ.
OBJ - это формат файлов описания геометрии, разработанный в Wavefront Technologies для их анимационного пакета Advanced Visualizer. Формат файла является открытым и был принят другими разработчиками приложений графики и может быть экспортирован/импортирован в e-Frontier"s Poser, Maya , XSI, Blender , MeshLab, Misfit Model 3D, 3D Studio Max и Rhinoceros 3D , Hexagon, CATIA , Newtek Lightwave, Art of Illusion , milkshape 3d,Modo , Cinema 4D , Zanoza Modeller, ПК ЛИРА , Mineways и т. д. По большей части это общепринятый формат.
Формат файлов OBJ - это простой формат данных, который содержит только 3D геометрию, а именно, позицию каждой вершины, связь координат текстуры с вершиной, нормаль для каждой вершины, а также параметры, которые создают полигоны.
Строки, начинающиеся с решётки(#), - это комментарии.
# Это комментарий
Obj файл содержит несколько типов определения:
# Список вершин, с координатами (x,y,z[,w]), w является не обязательным и по умолчанию 1.0. v 0.123 0.234 0.345 1.0 v ... ... # Текстурные координаты (u,v[,w]), w является не обязательным и по умолчанию 0. # Текстурная координата по y может быть указана как 1 - v, и при этом по x = u vt 0.500 -1.352 vt ... ... # Нормали (x,y,z); нормали могут быть не нормированными . . vn 0.707 0.000 0.707 vn ... ... # Параметры вершин в пространстве (u [,v] [,w]); свободная форма геометрического состояния (смотри ниже) vp 0.310000 3.210000 2.100000 vp ... ... # Определения поверхности (сторон) (смотри ниже) f 1 2 3 f 3/1 4/2 5/3 f 6/4/1 3/5/3 7/6/5 f 6//1 3//3 7//5 f ... ... # Группа g Group1 ... # Объект o Object1
Поверхность определяется в списке вершин, текстурных координат и нормалей. Полигоны такие как квадрат могут быть определены с помощью более 3 вершин/текстурных координат/нормалей.
Строка начинающаяся с f представляет собой индекс Поверхности. Каждая поверхность (полигон) может состоять из трех или более вершин.
F v1 v2 v3 v4 ...
Индексация начинается с первого элемента, а не с нулевого как принято в некоторых языках программирования, так же индексация может быть отрицательной. Отрицательный индекс указывает позицию относительно последнего элемента (индекс -1 указывает на последний элемент).
Наряду с вершинами могут сохраняться соответствующие индексы текстурных координат.
F v1/vt1 v2/vt2 v3/vt3 v4/vt4 ...
Также допустимо сохранение соответствующих индексов нормалей.
F v1/vt1/vn1 v2/vt2/vn2 v3/vt3/vn3 v4/vt4/vn4 ...
При отсутствии данных о текстурных координатах допустима запись с пропуском индексов текстур.
F v1//vn1 v2//vn2 v3//vn3 v4//vn4 ...
OBJ является одним из самых популярных форматов передачи 3-х мерной компьютерной геометрии. Информация о внешнем виде объектов(материалы) передается в файлах-спутниках в формате MTL (Material Library). OBJ при необходимости ссылается на такой файл с помощью директивы:
Mtllib [имя внешнего MTL файла]
MTL является стандартом, установленным компанией Wavefront Technologies. Вся информация представлена в ASCII виде и абсолютно читабельна для человека. Стандарт MTL так же очень популярен и поддерживается большинством пакетов для работы с 3D-графикой.
Информация о простых материалах в файле выглядит следующим образом:
Newmtl название_материала1 # Объявление очередного материала # Цвета Ka 1,000 1,000 0,000 # Цвет окружающего освещения (желтый) Kd 1,000 1,000 1,000 # Диффузный цвет (белый) # Параметры отражения Ks 0,000 0,000 0,000 # Цвет зеркального отражения (0;0;0 - выключен) Ns 10,000 # Коэффициент зеркального отражения (от 0 до 1000) # Параметры прозрачности d 0,9 # Прозрачность указывается с помощью директивы d Tr 0,9 # или в других реализациях формата с помощью Tr #Следующий материал newmtl название_материала2 ...
Наличие всех параметров необязательно. При отсутствии какого-либо параметра программа автоматически устанавливает его по умолчанию.