3D模型格式解析(OBJ)
生活随笔
收集整理的這篇文章主要介紹了
3D模型格式解析(OBJ)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- OBJ格式解析
- 一、OBJ格式
- 二、vtkOBJReader源碼解析
- 1.主要部分
- 總結
OBJ格式解析
通過解讀vtk源碼中對OBJ文件的讀取代碼,講解如何獲取obj模型的頂點(vertex)信息,法線信息,紋理信息以及點(Point)、線、面等主要元素的提取。一、OBJ格式
1.OBJ文件示例
# 一些注釋mtllib cube.mtl g default v -0.500000 -0.500000 0.500000 v 0.500000 -0.500000 0.500000 v -0.500000 0.500000 0.500000 v 0.500000 0.500000 0.500000 v -0.500000 0.500000 -0.500000 v 0.500000 0.500000 -0.500000 v -0.500000 -0.500000 -0.500000 v 0.500000 -0.500000 -0.500000 vt 0.001992 0.001992 vt 0.998008 0.001992 vt 0.001992 0.998008 vt 0.998008 0.998008 vt 0.001992 0.001992 vt 0.998008 0.001992 vt 0.001992 0.998008 vt 0.998008 0.998008 vt 0.001992 0.001992 vt 0.998008 0.001992 vt 0.001992 0.998008 vt 0.998008 0.998008 vt 0.001992 0.001992 vt 0.998008 0.001992 vt 0.001992 0.998008 vt 0.998008 0.998008 vt 0.001992 0.001992 vt 0.998008 0.001992 vt 0.001992 0.998008 vt 0.998008 0.998008 vt 0.998008 0.998008 vt 0.001992 0.998008 vt 0.998008 0.001992 vt 0.001992 0.001992 vn 0.000000 0.000000 1.000000 vn 0.000000 0.000000 1.000000 vn 0.000000 0.000000 1.000000 vn 0.000000 0.000000 1.000000 vn 0.000000 1.000000 0.000000 vn 0.000000 1.000000 0.000000 vn 0.000000 1.000000 0.000000 vn 0.000000 1.000000 0.000000 vn 0.000000 0.000000 -1.000000 vn 0.000000 0.000000 -1.000000 vn 0.000000 0.000000 -1.000000 vn 0.000000 0.000000 -1.000000 vn 0.000000 -1.000000 0.000000 vn 0.000000 -1.000000 0.000000 vn 0.000000 -1.000000 0.000000 vn 0.000000 -1.000000 0.000000 vn 1.000000 0.000000 0.000000 vn 1.000000 0.000000 0.000000 vn 1.000000 0.000000 0.000000 vn 1.000000 0.000000 0.000000 vn -1.000000 0.000000 0.000000 vn -1.000000 0.000000 0.000000 vn -1.000000 0.000000 0.000000 vn -1.000000 0.000000 0.000000 s 1 g pCube1 usemtl file1SG f 1/1/1 2/2/2 3/3/3 f 3/3/3 2/2/2 4/4/4 s 2 f 3/13/5 4/14/6 5/15/7 f 5/15/7 4/14/6 6/16/8 s 3 f 5/21/9 6/22/10 7/23/11 f 7/23/11 6/22/10 8/24/12 s 4 f 7/17/13 8/18/14 1/19/15 f 1/19/15 8/18/14 2/20/16 s 5 f 2/5/17 8/6/18 4/7/19 f 4/7/19 8/6/18 6/8/20 s 6 f 7/9/21 1/10/22 5/11/23 f 5/11/23 1/10/22 3/12/242.格式分析
- 注釋以#開頭;
- v表示模型的頂點坐標,表示為: v x y z
- vn:法線坐標,表示為:vn x y z
- vt:紋理坐標,一般每個坐標包含兩個值,表示為:vt u v w
- p:Point元素;
- l:線
- f:面,可以有多個頂點表示;
- f v1 v2 v3 … ,僅由三個以上頂點索引組成;
- f v1/vt1 v2/vt2 v3/vt3 …,由頂點和紋理索引組成;
- f v1//vn1 v2//vn2 v3//vn3 …,由頂點和法線索引組成;
- f v1/vt1/vn1 v2/vt2/vn2 v3/vt3/vn3 …,由頂點,紋理和法線索引組成;
索引的形成是按照頂點、法線,紋理信息在文件中的先后順序從1開始編號,可以采用負索引,表示倒數第幾個頂點,法線,紋理,一般由三個頂點組成一個面,也有多個頂點的情況。
其它更多信息請查看補充部分。
補充:
http://netghost.narod.ru/gff/graphics/summary/waveobj.htm#WAVEOBJ-DMYID.3
https://blog.csdn.net/qq_26900671/article/details/81739977
https://www.cnblogs.com/daofaziran/p/11540517.html
二、vtkOBJReader源碼解析
1.主要部分
/*---------------------------------------------------------------------------*\This is only partial support for the OBJ format, which is quite complicated. To find a full specification, search the net for "OBJ format", eg.:http://en.wikipedia.org/wiki/Objhttp://netghost.narod.ru/gff/graphics/summary/waveobj.htmWe support the following types:v <x> <y> <z>vertexvn <x> <y> <z>vertex normalvt <x> <y>texture coordinatef <v_a> <v_b> <v_c> ...polygonal face linking vertices v_a, v_b, v_c, etc. whichare 1-based indices into the vertex listf <v_a>/<t_a> <v_b>/<t_b> ...polygonal face as above, but with texture coordinates foreach vertex. t_a etc. are 1-based indices into the texturecoordinates list (from the vt lines)f <v_a>/<t_a>/<n_a> <v_b>/<t_b>/<n_b> ...polygonal face as above, with a normal at each vertex, as a1-based index into the normals list (from the vn lines)f <v_a>//<n_a> <v_b>//<n_b> ...polygonal face as above but without texture coordinates.Per-face tcoords and normals are supported by duplicatingthe vertices on each face as necessary.l <v_a> <v_b> ...lines linking vertices v_a, v_b, etc. which are 1-basedindices into the vertex listp <v_a> <v_b> ...points located at the vertices v_a, v_b, etc. which are 1-basedindices into the vertex list\*---------------------------------------------------------------------------*///部分代碼float xyz[3];//按行來解析數據...// in the OBJ format the first characters determine how to interpret the line://為定點信息if (strcmp(cmd, "v") == 0){// this is a vertex definition, expect three floats, separated by whitespace://獲取坐標值if (sscanf(pLine, "%f %f %f", xyz, xyz + 1, xyz + 2) == 3){points->InsertNextPoint(xyz);}else{vtkErrorMacro(<< "Error reading 'v' at line " << lineNr);everything_ok = false;}}//紋理坐標else if (strcmp(cmd, "vt") == 0){// this is a tcoord, expect two floats, separated by whitespace:// 獲取坐標if (sscanf(pLine, "%f %f", xyz, xyz + 1) == 2){tcoords->InsertNextTuple(xyz);}else{vtkErrorMacro(<< "Error reading 'vt' at line " << lineNr);everything_ok = false;}}//法線坐標else if (strcmp(cmd, "vn") == 0){// this is a normal, expect three floats, separated by whitespace://獲取坐標if (sscanf(pLine, "%f %f %f", xyz, xyz + 1, xyz + 2) == 3){normals->InsertNextTuple(xyz);hasNormals = true;}else{vtkErrorMacro(<< "Error reading 'vn' at line " << lineNr);everything_ok = false;}}//點元素else if (strcmp(cmd, "p") == 0){// this is a point definition, consisting of 1-based indices separated by whitespace and /pointElems->InsertNextCell(0); // we don't yet know how many points are to comeint nVerts = 0; // keep a count of how many there arewhile (everything_ok && pLine < pEnd){// find next non-whitespace characterwhile (isspace(*pLine) && pLine < pEnd) { pLine++; }if (pLine < pEnd) // there is still data left on this line{int iVert;if (sscanf(pLine, "%d", &iVert) == 1){pointElems->InsertCellPoint(iVert - 1);nVerts++;}else if (strcmp(pLine, "\\\n") == 0){// handle backslash-newline continuationif (fgets(rawLine, MAX_LINE, in) != NULL){lineNr++;pLine = rawLine;pEnd = rawLine + strlen(rawLine);continue;}else{vtkErrorMacro(<< "Error reading continuation line at line " << lineNr);everything_ok = false;}}else{vtkErrorMacro(<< "Error reading 'p' at line " << lineNr);everything_ok = false;}// skip over what we just sscanf'd// (find the first whitespace character)while (!isspace(*pLine) && pLine < pEnd) { pLine++; }}}if (nVerts < 1){vtkErrorMacro(<< "Error reading file near line " << lineNr<< " while processing the 'p' command");everything_ok = false;}// now we know how many points there were in this cellpointElems->UpdateCellCount(nVerts);}//線元素else if (strcmp(cmd, "l") == 0){// this is a line definition, consisting of 1-based indices separated by whitespace and /lineElems->InsertNextCell(0); // we don't yet know how many points are to comeint nVerts = 0; // keep a count of how many there arewhile (everything_ok && pLine < pEnd){// find next non-whitespace characterwhile (isspace(*pLine) && pLine < pEnd) { pLine++; }if (pLine < pEnd) // there is still data left on this line{int iVert, dummyInt;if (sscanf(pLine, "%d/%d", &iVert, &dummyInt) == 2){// we simply ignore texture informationlineElems->InsertCellPoint(iVert - 1);nVerts++;}else if (sscanf(pLine, "%d", &iVert) == 1){lineElems->InsertCellPoint(iVert - 1);nVerts++;}else if (strcmp(pLine, "\\\n") == 0){// handle backslash-newline continuationif (fgets(rawLine, MAX_LINE, in) != NULL){lineNr++;pLine = rawLine;pEnd = rawLine + strlen(rawLine);continue;}else{vtkErrorMacro(<< "Error reading continuation line at line " << lineNr);everything_ok = false;}}else{vtkErrorMacro(<< "Error reading 'l' at line " << lineNr);everything_ok = false;}// skip over what we just sscanf'd// (find the first whitespace character)while (!isspace(*pLine) && pLine < pEnd) { pLine++; }}}if (nVerts < 2){vtkErrorMacro(<< "Error reading file near line " << lineNr<< " while processing the 'l' command");everything_ok = false;}// now we know how many points there were in this celllineElems->UpdateCellCount(nVerts);}//面元素else if (strcmp(cmd, "f") == 0){// this is a face definition, consisting of 1-based indices separated by whitespace and /polys->InsertNextCell(0); // we don't yet know how many points are to cometcoord_polys->InsertNextCell(0);normal_polys->InsertNextCell(0);int nVerts = 0, nTCoords = 0, nNormals = 0; // keep a count of how many of each there arewhile (everything_ok && pLine < pEnd){// find the first non-whitespace characterwhile (isspace(*pLine) && pLine < pEnd) { pLine++; }if (pLine < pEnd) // there is still data left on this line{int iVert, iTCoord, iNormal;//1.獲取頂點、紋理、法線索引if (sscanf(pLine, "%d/%d/%d", &iVert, &iTCoord, &iNormal) == 3){polys->InsertCellPoint(iVert - 1); // convert to 0-based indexnVerts++;tcoord_polys->InsertCellPoint(iTCoord - 1);nTCoords++;normal_polys->InsertCellPoint(iNormal - 1);nNormals++;if (iTCoord != iVert)tcoords_same_as_verts = false;if (iNormal != iVert)normals_same_as_verts = false;}//2.獲取頂點、法線索引else if (sscanf(pLine, "%d//%d", &iVert, &iNormal) == 2){polys->InsertCellPoint(iVert - 1);nVerts++;normal_polys->InsertCellPoint(iNormal - 1);nNormals++;if (iNormal != iVert)normals_same_as_verts = false;}//3.獲取頂點、紋理索引else if (sscanf(pLine, "%d/%d", &iVert, &iTCoord) == 2){polys->InsertCellPoint(iVert - 1);nVerts++;tcoord_polys->InsertCellPoint(iTCoord - 1);nTCoords++;if (iTCoord != iVert)tcoords_same_as_verts = false;}//4.獲取頂點索引else if (sscanf(pLine, "%d", &iVert) == 1){polys->InsertCellPoint(iVert - 1);nVerts++;}else if (strcmp(pLine, "\\\n") == 0){// handle backslash-newline continuationif (fgets(rawLine, MAX_LINE, in) != NULL){lineNr++;pLine = rawLine;pEnd = rawLine + strlen(rawLine);continue;}else{vtkErrorMacro(<< "Error reading continuation line at line " << lineNr);everything_ok = false;}}else{vtkErrorMacro(<< "Error reading 'f' at line " << lineNr);everything_ok = false;}// skip over what we just read// (find the first whitespace character)while (!isspace(*pLine) && pLine < pEnd) { pLine++; }}}// count of tcoords and normals must be equal to number of vertices or zeroif (nVerts < 3 ||(nTCoords > 0 && nTCoords != nVerts) ||(nNormals > 0 && nNormals != nVerts)){vtkErrorMacro(<< "Error reading file near line " << lineNr<< " while processing the 'f' command");everything_ok = false;}// now we know how many points there were in this cellpolys->UpdateCellCount(nVerts);tcoord_polys->UpdateCellCount(nTCoords);normal_polys->UpdateCellCount(nNormals);// also make a note of whether any cells have tcoords, and whether any have normalsif (nTCoords > 0) { hasTCoords = true; }if (nNormals > 0) { hasNormals = true; }}else{//vtkDebugMacro(<<"Ignoring line: "<<rawLine);}總結
熟悉vtk框架,將obj轉換為其他模型文件以及提取有效信息。
總結
以上是生活随笔為你收集整理的3D模型格式解析(OBJ)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MATLAB高光谱图像构建KNN图
- 下一篇: 小白 LeetCode 242 有效的