Definindo um objeto 3D com o formato de arquivo OBJ

O formato de arquivo OBJ é um dos formatos de arquivo mais populares para armazenar modelos 3D. Ele é amplamente utilizado na indústria de jogos, animação e design de produtos. O formato OBJ é um arquivo de texto simples que contém informações sobre a geometria do modelo, como vértices, normais e coordenadas de textura. Neste artigo, discutiremos a estrutura do formato de arquivo OBJ, suas seções e instruções, e mostraremos como criar uma função em C++ que lê um arquivo OBJ e retorna um array de vértices que pode ser usado para renderizar o modelo 3D usando OpenGL.

O arquivo OBJ é um formato de arquivo de texto que contém informações sobre um modelo 3D. Ele é composto por várias seções, cada uma das quais contém instruções específicas para descrever a geometria do modelo.

A primeira seção é a seção de vértices, que começa com o comando “v” seguido de três números que representam as coordenadas x, y e z de cada vértice. Cada vértice é identificado por um número inteiro único.

A segunda seção é a seção de coordenadas de textura, que começa com o comando “vt” seguido de dois números que representam as coordenadas de textura u e v. Essas coordenadas são usadas para mapear uma textura na superfície do modelo.

A terceira seção é a seção de normais, que começa com o comando “vn” seguido de três números que representam as coordenadas x, y e z da normal de cada vértice. As normais são usadas para determinar a iluminação do modelo.

A quarta seção é a seção de faces, que começa com o comando “f” seguido de uma lista de três ou mais números que representam os índices dos vértices que formam cada face. Cada índice é um número inteiro que se refere ao número do vértice na seção de vértices.

O arquivo OBJ também pode incluir outros comandos, como o comando “mtllib” para especificar o arquivo de material para o modelo e o comando “usemtl” para aplicar um material a um grupo de faces.

Em resumo, o arquivo OBJ é uma forma conveniente de armazenar modelos 3D em um formato de arquivo de texto legível por máquina. Ele contém informações sobre a geometria do modelo, como vértices, coordenadas de textura, normais e faces, bem como outras informações úteis, como materiais e grupos de faces.

Estrutura do Formato de Arquivo OBJ

O formato de arquivo OBJ é dividido em várias seções, cada uma das quais é usada para armazenar informações específicas sobre o modelo 3D. As seções mais comuns são:

  • Vertices (V): esta seção contém as coordenadas 3D dos vértices do modelo. Cada linha nesta seção representa um único vértice e é escrita na forma “v x y z”, onde x, y e z são as coordenadas do vértice.
  • Normals (VN): esta seção contém as normais dos vértices do modelo. Cada linha nesta seção representa uma única normal e é escrita na forma “vn x y z”, onde x, y e z são as componentes da normal.
  • Texture Coordinates (VT): esta seção contém as coordenadas de textura do modelo. Cada linha nesta seção representa uma única coordenada de textura e é escrita na forma “vt u v”, onde u e v são as coordenadas de textura.
  • Faces (F): esta seção contém as informações sobre as faces do modelo. Cada linha nesta seção representa uma única face e é escrita na forma “f v1/vt1/vn1 v2/vt2/vn2 v3/vt3/vn3”, onde v1, v2 e v3 são os índices dos vértices da face, vt1, vt2 e vt3 são os índices das coordenadas de textura da face e vn1, vn2 e vn3 são os índices das normais da face.

Além dessas seções, há outras seções opcionais que podem conter informações sobre materiais, grupos e objetos.

Exemplo de arquivo OBJ

Aqui está um exemplo simples de um arquivo OBJ que contém informações sobre um modelo de cubo:

# Exemplo de arquivo OBJ para um cubo

# Definindo vértices
v 1.0 1.0 1.0
v 1.0 -1.0 1.0
v -1.0 -1.0 1.0
v -1.0 1.0 1.0
v 1.0 1.0 -1.0
v 1.0 -1.0 -1.0
v -1.0 -1.0 -1.0
v -1.0 1.0 -1.0

# Definindo faces
f 1 2 3
f 1 3 4
f 1 5 6
f 1 6 2
f 2 6 7
f 2 7 3
f 3 7 8
f 3 8 4
f 4 8 5
f 4 5 1
f 5 8 7
f 5 7 6

Neste exemplo, definimos os oito vértices do cubo usando o comando “v” seguido de suas coordenadas x, y e z. Em seguida, definimos as doze faces do cubo usando o comando “f” seguido dos índices dos vértices que formam cada face.

Observe que as faces são definidas no sentido anti-horário quando vistas de fora do objeto. Isso é importante para garantir que as normais do objeto sejam calculadas corretamente.

Este é apenas um exemplo simples de um arquivo OBJ. Arquivos OBJ mais complexos podem incluir outras informações, como coordenadas de textura e normais, bem como grupos de faces e materiais.

Aqui está um exemplo de arquivo OBJ que inclui informações sobre coordenadas de texturas e normais, bem como grupos de faces e materiais:

# Exemplo de arquivo OBJ com coordenadas de textura, normais, grupos de faces e materiais

# Definindo vértices
v 0.0 0.0 0.0
v 0.0 1.0 0.0
v 1.0 1.0 0.0
v 1.0 0.0 0.0
v 0.0 0.0 1.0
v 0.0 1.0 1.0
v 1.0 1.0 1.0
v 1.0 0.0 1.0

# Definindo coordenadas de textura
vt 0.0 0.0
vt 0.0 1.0
vt 1.0 1.0
vt 1.0 0.0

# Definindo normais
vn 0.0 0.0 1.0
vn 0.0 0.0 -1.0
vn 0.0 1.0 0.0
vn 0.0 -1.0 0.0
vn 1.0 0.0 0.0
vn -1.0 0.0 0.0

# Definindo materiais
mtllib exemplo.mtl
usemtl vermelho

# Definindo grupos de faces
g frente
usemtl vermelho
f 1/1/1 2/2/1 3/3/1
f 1/1/1 3/3/1 4/4/1
g traseira
usemtl azul
f 5/1/2 8/2/2 7/3/2
f 5/1/2 7/3/2 6/4/2
g esquerda
usemtl verde
f 1/1/3 5/2/3 6/3/3
f 1/1/3 6/3/3 2/4/3
g direita
usemtl amarelo
f 4/1/4 3/2/4 7/3/4
f 4/1/4 7/3/4 8/4/4
g topo
usemtl rosa
f 2/1/5 6/2/5 7/3/5
f 2/1/5 7/3/5 3/4/5
g base
usemtl roxo
f 1/1/6 4/2/6 8/3/6
f 1/1/6 8/3/6 5/4/6

Neste exemplo, definimos os oito vértices do cubo usando o comando “v” seguido de suas coordenadas x, y e z. Em seguida, definimos as coordenadas de textura para cada vértice usando o comando “vt” seguido de suas coordenadas u e v.

Definimos as normais para cada vértice usando o comando “vn” seguido das coordenadas x, y e z da normal.

Em seguida, definimos os materiais para o modelo usando o comando “mtllib” seguido do nome do arquivo .mtl onde os materiais são definidos. No exemplo acima, o arquivo .mtl é chamado de “exemplo.mtl”.

Para cada grupo de faces, podemos definir o material a ser usado usando o comando “usemtl” seguido do nome do material definido no arquivo .mtl.

Em cada grupo de faces, definimos as faces que compõem o grupo usando o comando “f” seguido dos índices dos vértices, coordenadas de textura e normais para cada face.

Por exemplo, na seção “frente”, usamos o material “vermelho” definido no arquivo .mtl. As duas faces que compõem este grupo são definidas pelos seguintes comandos:

f 1/1/1 2/2/1 3/3/1
f 1/1/1 3/3/1 4/4/1

Isso significa que a primeira face consiste nos vértices 1, 2 e 3, cada um com suas respectivas coordenadas de textura e normais, e a segunda face consiste nos vértices 1, 3 e 4, novamente com suas respectivas coordenadas de textura e normais.

O mesmo processo é repetido para os outros grupos de faces, cada um com seu próprio material e conjunto de faces.

Este arquivo OBJ pode ser importado em um programa OpenGL para renderizar um cubo texturizado e colorido usando diferentes materiais em cada face.

Criando uma Função C++ para Ler Arquivos OBJ

Aqui, vamos mostrar como criar uma função C++ que lê um arquivo OBJ e retorna um array de vértices. Para isso, vamos supor que o arquivo OBJ contém apenas informações sobre vértices e faces.

Para ler o arquivo OBJ, usaremos as seguintes etapas:

  1. Abrir o arquivo e ler o conteúdo.
  2. Ler cada linha do arquivo e analisá-la para obter as informações sobre vértices e faces.
  3. Armazenar as informações dos vértices em um vetor de vértices.
  4. Armazenar as informações das faces em um vetor de índices.
  5. Retornar o vetor de vértices.

Aqui está o código da função:

#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>

struct Vertex {
  float x, y, z;
};

std::vector<Vertex> readObjFile(const std::string& filename) {
  std::vector<Vertex> vertices;
  std::vector<unsigned int> indices;

  std::ifstream file(filename);
  if (!file) {
     std::cerr << "Failed to open file: " << filename << std::endl;
     return vertices;
  }

  std::string line;
  while (std::getline(file, line)) {
     std::istringstream iss(line);
     std::string type;
     iss >> type;

     if (type == "v") {
        Vertex v;
        iss >> v.x >> v.y >> v.z;
        vertices.push_back(v);
     } else if (type == "f") {
        unsigned int v1, v2, v3;
        iss >> v1 >> v2 >> v3;
        indices.push_back(v1 - 1);
        indices.push_back(v2 - 1);
        indices.push_back(v3 - 1);
     }

  }

  std::vector<Vertex> result(vertices.size());
  for (unsigned int i = 0; i < vertices.size(); ++i) {
     result[i] = vertices[i];
  }

  return result;
}

Nesta função, criamos um vetor de vértices e um vetor de índices. Percorremos cada linha do arquivo OBJ e, se a linha começar com “v”, adicionamos um novo vértice ao vetor de vértices. Se a linha começar com “f”, adicionamos os índices dos vértices que formam a face ao vetor de índices. No final, criamos um novo vetor de vértices para retornar, copiando as informações do vetor original.

Conclusão

O formato de arquivo OBJ é um formato de arquivo popular para armazenar modelos 3D. É um arquivo de texto simples que contém informações sobre a geometria do modelo. Neste artigo, discutimos a estrutura do formato de arquivo OBJ, suas seções e instruções, e mostramos como criar uma função em C++ que lê um arquivo OBJ e retorna um array de vértices que pode ser usado para renderizar o modelo 3D usando OpenGL. Esperamos que este artigo tenha sido útil para entender o formato de arquivo OBJ e como trabalhar com ele em C++.