private void AddFace(string values)
{
var currentGroup = this.CurrentGroup;
var builder = currentGroup.MeshBuilder;
var positions = builder.Positions;
var textureCoordinates = builder.TextureCoordinates;
var normals = builder.Normals;
Dictionary<int, int> smoothingGroupMap = null;
// If a smoothing group is defined, get the map from obj-file-index to current-group-vertex-index.
if (this.currentSmoothingGroup != 0)
{
if (!this.smoothingGroupMaps.TryGetValue(this.currentSmoothingGroup, out smoothingGroupMap))
{
smoothingGroupMap = new Dictionary<int, int>();
this.smoothingGroupMaps.Add(this.currentSmoothingGroup, smoothingGroupMap);
}
}
var fields = values.SplitOnWhitespace();
var faceIndices = new List<int>();
foreach (var field in fields)
{
if (string.IsNullOrEmpty(field))
{
continue;
}
var ff = field.Split('/');
int vi = int.Parse(ff[0]);
int vti = ff.Length > 1 && ff[1].Length > 0 ? int.Parse(ff[1]) : int.MaxValue;
int vni = ff.Length > 2 && ff[2].Length > 0 ? int.Parse(ff[2]) : int.MaxValue;
// Handle relative indices (negative numbers)
if (vi < 0)
{
vi = this.Points.Count + vi + 1;
}
if (vti < 0)
{
vti = this.TextureCoordinates.Count + vti + 1;
}
if (vni < 0)
{
vni = this.Normals.Count + vni + 1;
}
// Check if the indices are valid
if (vi - 1 >= this.Points.Count)
{
if (this.IgnoreErrors)
{
return;
}
throw new FileFormatException(string.Format("Invalid vertex index ({0}) on line {1}.", vi, this.currentLineNo));
}
if (vti == int.MaxValue)
{
// turn off texture coordinates in the builder
builder.CreateTextureCoordinates = false;
}
if (vni == int.MaxValue)
{
// turn off normals in the builder
builder.CreateNormals = false;
}
// check if the texture coordinate index is valid
if (builder.CreateTextureCoordinates && vti - 1 >= this.TextureCoordinates.Count)
{
if (this.IgnoreErrors)
{
return;
}
throw new FileFormatException(
string.Format(
"Invalid texture coordinate index ({0}) on line {1}.", vti, this.currentLineNo));
}
// check if the normal index is valid
if (builder.CreateNormals && vni - 1 >= this.Normals.Count)
{
if (this.IgnoreErrors)
{
return;
}
throw new FileFormatException(
string.Format("Invalid normal index ({0}) on line {1}.", vni, this.currentLineNo));
}
bool addVertex = true;
if (smoothingGroupMap != null)
{
int vix;
if (smoothingGroupMap.TryGetValue(vi, out vix))
{
// use the index of a previously defined vertex
addVertex = false;
}
else
{
// add a new vertex
vix = positions.Count;
smoothingGroupMap.Add(vi, vix);
}
faceIndices.Add(vix);
}
else
{
// if smoothing is off, always add a new vertex
faceIndices.Add(positions.Count);
}
if (addVertex)
{
// add vertex
positions.Add(this.Points[vi - 1]);
// add texture coordinate (if enabled)
if (builder.CreateTextureCoordinates)
{
textureCoordinates.Add(this.TextureCoordinates[vti - 1]);
}
// add normal (if enabled)
if (builder.CreateNormals)
{
normals.Add(this.Normals[vni - 1]);
}
}
}
if (faceIndices.Count <= 4)
{
// add triangles or quads
builder.AddPolygon(faceIndices);
}
else
{
// add triangles by cutting ears algorithm
// this algorithm is quite expensive...
builder.AddPolygonByCuttingEars(faceIndices);
}
}