Created
March 4, 2014 06:23
-
-
Save occar421/9341260 to your computer and use it in GitHub Desktop.
Discussion of .srf file linq parser 2
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"); | |
} | |
var splitedByZ = stream.Skip(1).GroupBy(x => x.First() == 'Z'); | |
var normalLines = splitedByZ.Single(x => !x.Key); | |
var zBuf = splitedByZ.SingleOrDefault(x => x.Key); | |
IDictionary<int, int> alphaData; | |
IEnumerable<int> zData; | |
IEnumerable<int> lightData; | |
if (zBuf == null) | |
{ | |
alphaData = new Dictionary<int, int>(); | |
zData = new int[0]; | |
lightData = new int[0]; | |
} | |
else | |
{ | |
var zLines = zBuf.GroupBy(x => x.Skip(1).First()).Select(x => new KeyValuePair<char, IEnumerable<int>>(x.Key, x.SelectMany(y => y.Split(' ').Skip(1)).Select(y => int.Parse(y)))); | |
//Alpha | |
var alphaLines = zLines.SingleOrDefault(x => x.Key == 'A').Value; | |
if (alphaLines == null) | |
{ | |
alphaData = new Dictionary<int, int>(); | |
} | |
else | |
{ | |
var alphaGroup = alphaLines.Select((x, i) => new { Index = i, Value = x }).GroupBy(x => x.Index % 2 == 0); | |
alphaData = alphaGroup.Single(x => x.Key).Zip(alphaGroup.Single(x => !x.Key), (key, value) => new { Key = key.Value, Value = value.Value }) | |
.ToDictionary(x => x.Key, x => x.Value); | |
} | |
//Z | |
zData = zLines.SingleOrDefault(x => x.Key == 'Z').Value ?? new int[0]; | |
//Light | |
lightData = zLines.SingleOrDefault(x => x.Key == 'L').Value ?? new int[0]; | |
} | |
//Vertex | |
var vertexLines = normalLines.TakeWhile(x => x.First() == 'V'); | |
Vertices = vertexLines.Select(x => Vertex.Create(x)); | |
//Face | |
var faceLines = normalLines.SkipWhile(x => x.First() == 'V'); | |
Faces = Face.CreateFaces(faceLines, alphaData, zData, lightData); | |
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 IsCpuRenderIgnore { get; set; } | |
public bool IsLight { get; set; } | |
static public IEnumerable<Face> CreateFaces(IEnumerable<string> data, IDictionary<int, int> alpha, IEnumerable<int> z, IEnumerable<int> light) | |
{ | |
var e = data.GetEnumerator(); | |
bool isFace = false; | |
Face f = new Face(); | |
for (var i = 0; e.MoveNext(); i++) | |
{ | |
switch (e.Current.First()) | |
{ | |
case 'F': | |
isFace = true; | |
break; | |
case 'B': | |
if (!isFace) | |
{ | |
throw new FileFormatException("F行とE行の外にB行があります。"); | |
} | |
f.IsEmit = true; | |
break; | |
case 'C': | |
if (!isFace) | |
{ | |
throw new FileFormatException("F行とE行の外にC行があります。"); | |
} | |
var color = e.Current.Split(' '); | |
if (color.Length == 4) | |
{ | |
f.Color = new Color4() | |
{ | |
R = float.Parse(color[1]) / 255f, | |
G = float.Parse(color[2]) / 255f, | |
B = float.Parse(color[3]) / 255f, | |
A = alpha.ContainsKey(i) ? alpha[i] : 0f | |
}; | |
} | |
else if (color.Length == 2) | |
{ | |
f.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), | |
A = alpha.ContainsKey(i) ? alpha[i] : 0f | |
}; | |
} | |
else | |
{ | |
throw new FileFormatException("色のフォーマットが異常です。" + string.Concat(color)); | |
} | |
break; | |
case 'N': | |
if (!isFace) | |
{ | |
throw new FileFormatException("F行とE行の外にN行があります。"); | |
} | |
var normal = e.Current.Split(' '); | |
f.Normal = new Vector3() | |
{ | |
X = -float.Parse(normal[1]), | |
Y = float.Parse(normal[2]), | |
Z = float.Parse(normal[3]) | |
}; | |
f.Centroid = new Vector3() | |
{ | |
X = -float.Parse(normal[4]), | |
Y = float.Parse(normal[5]), | |
Z = float.Parse(normal[6]) | |
}; | |
break; | |
case 'V': | |
if (!isFace) | |
{ | |
throw new FileFormatException("F行とE行の外に面定義と思われるV行があります。"); | |
} | |
f.VertexIndices = e.Current.Split(' ').Skip(1).Select(x => int.Parse(x)); | |
break; | |
case 'E': | |
if (isFace) | |
{ | |
f.IsCpuRenderIgnore = z.Contains(i); | |
f.IsLight = light.Contains(i); | |
yield return f; | |
} | |
else | |
{ | |
yield break; | |
} | |
isFace = false; | |
break; | |
default: | |
break; | |
} | |
} | |
} | |
} |
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