OBJ 文件在面值中出现击穿错误
本文关键字:错误 文件 OBJ | 更新日期: 2023-09-27 18:37:23
我正在尝试理解一个obj文件,以便我可以将其分解以进行导入。 现在,我的示例是一个简单的金字塔,使用3ds max设计。教程出现了一些小错误。
到目前为止,我理解了一点,但这些加载正常:
v is vertex(point in space),
vn is vertex normal(don't understand why needed) but imported ok
vt is vertex texture
但文件中的下一个是 F & S,如下所示:
s 4
f 1/1/1 2/2/1 3/3/1
s 2
f 1/1/2 3/4/2 4/5/2
首先,我真的不明白s
是什么以及为什么它会呈指数级增长?
更重要的是,我没有得到f
的细分,根据wikki:
f v1/vt1/vn1
对我来说,这看起来像v1
是顶点,vt
是纹理,vn
是正常的,但为什么他们会在文件中重复呢?所以我认为我的猜测是错误的。
问题是我的加载对象能够填充除面之外的所有内容,除非面与文件底部的多边形相同,然后为 0,但这也没有意义!
请解决我的困惑,谢谢!
这是代码和文件:
[代码]
public static ObjVolume LoadFromString(string obj)
{
// Seperate lines from the file
List<String> lines = new List<string>(obj.Split(''n'));
// Lists to hold model data
List<Vector3> verts = new List<Vector3>();
List<Vector3> colors = new List<Vector3>();
List<Vector2> texs = new List<Vector2>();
List<Tuple<int, int, int>> faces = new List<Tuple<int, int, int>>();
// Read file line by line
foreach (String line in lines)
{
if (line.StartsWith("v ")) // Vertex definition
{
// Cut off beginning of line
String temp = line.Substring(2);
temp.TrimStart( );
Vector3 vec = new Vector3();
if (temp.Count((char c) => c == ' ') == 3) // Check if there's enough elements for a vertex
{
String[] vertparts = temp.Split(' ');
vertparts[3].Replace("'r","");
// Attempt to parse each part of the vertice
bool success = float.TryParse(vertparts[1], out vec.X);
success |= float.TryParse(vertparts[2], out vec.Y);
success |= float.TryParse(vertparts[3], out vec.Z);
// Dummy color/texture coordinates for now
colors.Add(new Vector3((float)Math.Sin(vec.Z), (float)Math.Sin(vec.Z), (float)Math.Sin(vec.Z)));
texs.Add(new Vector2((float)Math.Sin(vec.Z), (float)Math.Sin(vec.Z)));
// If any of the parses failed, report the error
if (!success)
{
Console.WriteLine("Error parsing vertex: {0}", line);
}
}
verts.Add(vec);
}
else if (line.StartsWith("f ")) // Face definition
{
// Cut off beginning of line
String temp = line.Substring(2);
Tuple<int, int, int> face = new Tuple<int, int, int>(0, 0, 0);
if (temp.Count((char c) => c == ' ') == 3) // Check if there's enough elements for a face
{
String[] faceparts = temp.Split(' ');
int i1, i2, i3;
// Attempt to parse each part of the face
bool success = int.TryParse(faceparts[0], out i1);
success |= int.TryParse(faceparts[1], out i2);
success |= int.TryParse(faceparts[2], out i3);
// If any of the parses failed, report the error
if (!success)
{
Console.WriteLine("Error parsing face: {0}", line);
}
else
{
// Decrement to get zero-based vertex numbers
face = new Tuple<int, int, int>(i1 - 1, i2 - 1, i3 - 1);
faces.Add(face);
}
}
}
}
// Create the ObjVolume
ObjVolume vol = new ObjVolume();
vol.vertices = verts.ToArray();
vol.faces = new List<Tuple<int, int, int>>(faces);
vol.colors = colors.ToArray();
vol.texturecoords = texs.ToArray();
return vol;
}
# 3ds Max Wavefront OBJ Exporter v0.97b - (c)2007 guruware
# File Created: 27.02.2016 07:40:58
mtllib test1.mtl
#
# object Pyramid001
#
v -15.7732 14.1346 5.0964
v -23.0566 0.0050 13.3650
v -8.4899 0.0050 13.3650
v -8.4899 0.0050 -3.1722
v -23.0566 0.0050 -3.1722
v -15.7732 0.0050 5.0964
# 6 vertices
vn 0.0000 0.5051 0.8631
vn 0.8889 0.4582 -0.0000
vn 0.0000 0.5051 -0.8631
vn -0.8889 0.4582 -0.0000
vn 0.0000 -1.0000 -0.0000
# 5 vertex normals
vt 0.5000 1.0000 0.0000
vt 0.0000 0.0000 0.0000
vt 1.0000 0.0000 0.0000
vt 0.0596 0.0000 0.0000
vt 1.0596 0.0000 0.0000
vt 0.0000 1.0000 0.0000
vt 0.5000 0.5000 0.0000
vt 1.0000 1.0000 0.0000
# 8 texture coords
g Pyramid001
usemtl wire_154215229
s 4
f 1/1/1 2/2/1 3/3/1
s 2
f 1/1/2 3/4/2 4/5/2
s 16
f 1/1/3 4/2/3 5/3/3
s 32
f 1/1/4 5/4/4 2/5/4
s 8
f 2/6/5 6/7/5 3/8/5
f 3/8/5 6/7/5 4/3/5
f 4/3/5 6/7/5 5/2/5
f 5/2/5 6/7/5 2/6/5
# 0 polygons - 8 triangles
[/代码]
你对 V/Vt/Vn 的看法是对的。您再次需要它来了解人脸是如何连接的,每张脸的纹理坐标和法线是什么。它们不会在文件中重复,f 1/4/10 2/5/6 3/7/11 表示此面具有顶点 v1、v2 和 v3,纹理坐标位于 vt4、vt5 和 vt7,法线坐标为 vn10、vn6 和 vn11。请注意,v、vt 和 vn 的索引与它们在 obj 文件中出现的顺序相同。我建议你暂时忽略vt和vn,只尝试使用f后的第一个数字显示人脸。对于前面的示例,可以连接 v1、v2 和 v3,并且应该获得正确的人脸。稍后,您还可以添加法线和纹理,以获得具有纹理和正确照明的完整形状。请注意,仅当您拥有提供纹理的图像图集时,vt 才有效。VTS实际上指的是图像纹理的坐标。