Created
March 2, 2014 11:51
-
-
Save occar421/9305463 to your computer and use it in GitHub Desktop.
Discussion of .srf file linq parser 1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public void Parse(IEnumerable<string> data) | |
{ | |
DateTime start = DateTime.Now; | |
var stream = data.Where(x => !string.IsNullOrEmpty(x)); | |
if (stream.First().StartsWith("surf", false, null)) | |
{ | |
throw new FileFormatException("SURF Header"); | |
} | |
//Alpha | |
var alphaLines = stream.Where(x => x.StartsWith("ZA")); | |
var alphaArray = alphaLines.SelectMany(x => x.Split(' ').Skip(1)); | |
var alphaDictionary = Enumerable.Zip(alphaArray.Alternate(2), alphaArray.Skip(1).Alternate(2), (x, y) => new KeyValuePair<int, float>(int.Parse(x), float.Parse(y) / 255f)).ToDictionary(item => item.Key, item => item.Value); | |
//Z | |
var zLines = stream.Where(x => x.StartsWith("ZZ")); | |
var zArray = zLines.SelectMany(x => x.Split(' ').Skip(1)).Select(x => int.Parse(x)); | |
//Light | |
var lightLines = stream.Where(x => x.StartsWith("ZL")); | |
var lightArray = lightLines.SelectMany(x => x.Split(' ').Skip(1)).Select(x => int.Parse(x)); | |
//Vertices | |
var vertexLines = stream.Skip(1).TakeWhile(x => x.StartsWith("V")); | |
Vertices = vertexLines.AsParallel().Select(x => Vertex.Create(x)); | |
//Faces | |
var faceLines = stream.Skip(1).SkipWhile(x => x.StartsWith("V")).ComparerTakeWhile((now, next) => !(now.StartsWith("E") && next.StartsWith("E")), "", ""); | |
Faces = faceLines.HeadSeparate(x => x.StartsWith("F")).AsParallel().Select((x, i) => Face.Create(x, i, alphaDictionary, zArray, lightArray)); | |
RequiredTime = DateTime.Now - start; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct Face | |
{ | |
public IEnumerable<int> VertexIndices { get; set; } | |
public Color4 Color { get; set; } | |
public bool IsEmit { get; set; } | |
public Vector3 Normal { get; set; } | |
public Vector3 Centroid { get; set; } | |
public bool IsDoubleSide { get; set; } | |
public bool IsCpuRenderIgnore { get; set; } | |
public bool IsLight { get; set; } | |
static public Face Create(IEnumerable<string> data, int index, IDictionary<int, float> alpha, IEnumerable<int> z, IEnumerable<int> light) | |
{ | |
var result = new Face(); | |
result.IsEmit = data.Any(x => x.StartsWith("B")); | |
var color = data.Single(x => x.StartsWith("C")).Split(' '); | |
if (color.Length == 4) | |
{ | |
result.Color = new Color4() | |
{ | |
R = float.Parse(color[1]) / 255f, | |
G = float.Parse(color[2]) / 255f, | |
B = float.Parse(color[3]) / 255f, | |
A = alpha.ContainsKey(index) ? alpha[index] : 0f | |
}; | |
} | |
else if (color.Length == 2) | |
{ | |
result.Color = new Color4() | |
{ | |
R = (float)Math.Floor(((int.Parse(color[1]) & 992) >> 5) * 255.0f / 31.0f), | |
G = (float)Math.Floor(((int.Parse(color[1]) & 31744) >> 10) * 255.0f / 31.0f), | |
B = (float)Math.Floor(((int.Parse(color[1]) & 31)) * 255.0f / 31.0f) | |
}; | |
} | |
else | |
{ | |
throw new FileFormatException("色のフォーマットが異常です。" + string.Concat(color)); | |
} | |
var normal = data.Single(x => x.StartsWith("N")).Split(' '); | |
result.Normal = new Vector3() | |
{ | |
X = -float.Parse(normal[1]), | |
Y = float.Parse(normal[2]), | |
Z = float.Parse(normal[3]) | |
}; | |
result.Centroid = new Vector3() | |
{ | |
X = -float.Parse(normal[4]), | |
Y = float.Parse(normal[5]), | |
Z = float.Parse(normal[6]) | |
}; | |
result.IsDoubleSide = result.Normal == Vector3.Zero; | |
var indices = data.Single(x => x.StartsWith("V")).Split(' '); | |
result.VertexIndices = indices.Skip(1).Select(x => int.Parse(x)).Reverse(); | |
result.IsCpuRenderIgnore = z.Contains(index); | |
result.IsLight = light.Contains(index); | |
return result; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
static class LinqExtension | |
{ | |
public static IEnumerable<T> ComparerTakeWhile<T>(this IEnumerable<T> obj, Func<T, T, bool> comparer, T firstItem, T lastItem) | |
{ | |
if (obj == null) | |
{ | |
yield break; | |
} | |
var e = obj.GetEnumerator(); | |
if (!e.MoveNext()) | |
{ | |
yield break; | |
} | |
T now = e.Current; | |
if (!comparer(firstItem, now)) | |
{ | |
yield break; | |
} | |
while (e.MoveNext()) | |
{ | |
if (!comparer(now, e.Current)) | |
{ | |
yield return now; | |
yield break; | |
} | |
yield return now; | |
now = e.Current; | |
} | |
if (comparer(now, lastItem)) | |
{ | |
yield return now; | |
} | |
} | |
public static IEnumerable<IEnumerable<T>> HeadSeparate<T>(this IEnumerable<T> obj, Func<T, bool> head) | |
{ | |
if (obj == null) | |
{ | |
yield break; | |
} | |
var predicate = (Func<T, bool>)(x => !head(x)); | |
IEnumerable<T> current, next = obj, sample; | |
while (next.Any()) | |
{ | |
sample = next.Skip(1).TakeWhile(predicate); | |
current = next.Take(sample.Count() + 1); | |
yield return current; | |
next = next.Skip(1).SkipWhile(predicate); | |
} | |
} | |
public static IEnumerable<T> Alternate<T>(this IEnumerable<T> obj, int step) | |
{ | |
var e = obj.GetEnumerator(); | |
for (int i = 0; e.MoveNext(); i++) | |
{ | |
if (i % step == 0) | |
{ | |
yield return e.Current; | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct Vertex | |
{ | |
public Vector3 Position { get; set; } | |
public bool IsRound { get; set; } | |
public Vector3 Normal { get; set; } | |
static public Vertex Create(string data) | |
{ | |
var e = data.Split(' '); | |
return new Vertex() | |
{ | |
Position = new Vector3() | |
{ | |
X = -float.Parse(e[1]), | |
Y = float.Parse(e[2]), | |
Z = float.Parse(e[3]) | |
}, | |
IsRound = (e.Length > 5 && "R".Equals(e[4])) | |
}; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment