一、.obj文件簡介
OBJ文件是一種包含三維幾何體信息的文件格式,它包括物體的位置、法線、紋理坐標和面信息。該格式最初是由AutoCAD創建的,現在被廣泛用於3D圖形應用程序中
OBJ文件是一種包含模型和材質數據的文本文件,其結構非常簡單:文件頭信息、頂點和法線、紋理坐標、面等。在OBJ文件中,每行都表示一個參數,用空格或者製表符分隔。這使得它成為一種簡單、通用的格式,因為幾乎任何3D圖形軟件都能讀取和寫入OBJ格式。因此,OBJ文件成為了3D圖形軟件間通用的橋樑。
二、.obj文件的結構
OBJ文件的結構由一系列的組成部分組成:
1.文件頭
OBJ文件格式的第一行通常是格式說明。在這一行中,#代表注釋(注釋應該位於該行的開頭),後面可以跟着一些數字或字母代表該文件的格式版本、作者等信息。
# This is a Wavefront OBJ file # File created by Blender
2.頂點和法線
OBJ文件保存的每個物體頂點都以”v”開頭的一行開始,後面跟着xyz三個浮點數表示三維位置坐標。此外,以”vn”開頭的行代表了每個頂點的法向量。
# Vertex coordinates v 0.0 0.0 0.0 v 1.0 0.0 0.0 v 0.0 1.0 0.0 vn 0.0 0.0 1.0 vn 0.0 0.0 1.0 vn 0.0 0.0 1.0
3.紋理坐標
使用”vt”開頭的行表示每個頂點的紋理坐標。紋理坐標通常是二維的,以u,v兩個浮點數表示。
# Texture coordinates vt 0.0 0.0 vt 1.0 0.0 vt 0.0 1.0
4.面
面的定義以”f”開頭的一行開始,後跟一系列整數表示該面頂點的索引號。索引號指向前面定義的頂點列表和紋理坐標列表。面的定義可以使用兩種不同的格式表示:單個面和多重面。單個面只包含三個頂點,多重面可以包含任意數量的頂點。
# Face definitions f 1/1/1 2/2/2 3/3/3 f 1/1/1 3/3/3 4/4/4
5.材質和組
OBJ文件格式還支持材質和組。使用”mtllib”定義材質庫,使用”usemtl”定義使用材質,使用”g”定義物體組。
# Material definitions mtllib example.mtl usemtl red usemtl green # Object groups g object1 g object2
三、示例代碼
下面是一個讀取並打印OBJ文件的C++函數示例:
#include #include #include #include #include struct Vec3 { float x, y, z; }; struct Vec2 { float u, v; }; struct TriangleIndex { int vertexIdx[3]; int normalIdx[3]; int texIdx[3]; }; std::vector vertices; std::vector normals; std::vector texCoords; std::vector indices; void loadObj(const std::string& filename) { std::ifstream file(filename); std::string line; while (std::getline(file, line)) { std::istringstream iss(line); char c; if (!(iss >> c)) continue; switch (c) { case 'v': if (iss.peek() == 'n') { Vec3 normal; iss >> c; iss >> normal.x; iss >> normal.y; iss >> normal.z; normals.push_back(normal); } else if (iss.peek() == 't') { Vec2 texCoord; iss >> c; iss >> texCoord.u; iss >> texCoord.v; texCoords.push_back(texCoord); } else { Vec3 vertex; iss >> vertex.x; iss >> vertex.y; iss >> vertex.z; vertices.push_back(vertex); } break; case 'f': { TriangleIndex index; for (int i = 0; i > index.vertexIdx[i]; if (iss.peek() == '/') { iss.ignore(); if (iss.peek() != '/') { iss >> index.texIdx[i]; } if (iss.peek() == '/') { iss.ignore(); iss >> index.normalIdx[i]; } } } indices.push_back(index); break; } } } } int main() { std::string filename = "example.obj"; loadObj(filename); printf("Vertices:\n"); for (const auto& v : vertices) { printf("%f %f %f\n", v.x, v.y, v.z); } printf("Normals:\n"); for (const auto& n : normals) { printf("%f %f %f\n", n.x, n.y, n.z); } printf("Texture coordinates:\n"); for (const auto& t : texCoords) { printf("%f %f\n", t.u, t.v); } printf("Faces:\n"); for (const auto& i : indices) { printf("%d/%d/%d %d/%d/%d %d/%d/%d\n", i.vertexIdx[0], i.texIdx[0], i.normalIdx[0], i.vertexIdx[1], i.texIdx[1], i.normalIdx[1], i.vertexIdx[2], i.texIdx[2], i.normalIdx[2]); } return 0; }
原創文章,作者:EAVKW,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/371105.html