static Token GetNextToken(ref string s, ref int pos, ref int ln, ref int col, ref string err) { Token tkn = null; char ch1 = ' '; char ch2 = ' '; StringBuilder sb = new StringBuilder(); for (; ; ) { // 文字列外 if (s.Length <= pos) return null; ch1 = s[pos]; if (IsIgnoredChar(ch1)) { NextChar(ref s, ref pos, ref ln, ref col); } else { break; } } // 禁則文字 if (IsInvalidChar(ch1)) { err = "Invalid char : " + ch1 + " line =" + ln.ToString() + " col = " + col.ToString(); return null; } if (IsLetterChar(ch1)) { // 識別文字列 var _ln = ln; var _col = col; while ((IsLetterChar(ch1) || IsDigitChar(ch1)) && pos < s.Length) { sb.Append(ch1); NextChar(ref s, ref pos, ref ln, ref col); if (pos < s.Length) { ch1 = s[pos]; } } tkn = new Token(sb.ToString(), _ln, _col, false); } else if (IsStartEndString(ch1)) { // 文字列 var _ln = ln; var _col = col; NextChar(ref s, ref pos, ref ln, ref col); ch1 = s[pos]; while (!IsStartEndString(ch1) && pos < s.Length) { if (ch1 == '\\') { NextChar(ref s, ref pos, ref ln, ref col); if (pos < s.Length) { ch1 = s[pos]; } } sb.Append(ch1); NextChar(ref s, ref pos, ref ln, ref col); if (pos < s.Length) { ch1 = s[pos]; } } NextChar(ref s, ref pos, ref ln, ref col); tkn = new Token(sb.ToString(), _ln, _col, true); } else if (IsNumber(ch1)) { // 数値 var _ln = ln; var _col = col; while ((IsDigitChar(ch1) || ch1 == '.') && pos < s.Length) { sb.Append(ch1); NextChar(ref s, ref pos, ref ln, ref col); ch1 = s[pos]; } var f = 0.0; if (double.TryParse(sb.ToString(), System.Globalization.NumberStyles.Float, NFI, out f)) { return new Token(f, _ln, _col); } else { err = "Invalid number : " + sb.ToString() + " line =" + ln.ToString() + " col = " + col.ToString(); return null; } } else { // その他 if (pos + 1 < s.Length) { // 2文字演算子 ch2 = s[pos + 1]; string ch = ch1.ToString() + ch2.ToString(); if (ope2.ContainsKey(ch)) { tkn = new Token(ope2[ch], ln, col); NextChar(ref s, ref pos, ref ln, ref col); NextChar(ref s, ref pos, ref ln, ref col); return tkn; } } // 1文字演算子 if (ope1.ContainsKey(ch1)) { tkn = new Token(ope1[ch1], ln, col); NextChar(ref s, ref pos, ref ln, ref col); return tkn; } } if (tkn != null && tkn.Kind == TokenKind.Letter) { // 実は識別文字列は登録済み? if (opemulti.ContainsKey(tkn.Letter)) { tkn = new Token(opemulti[tkn.Letter], tkn.Line, tkn.Col); } return tkn; } else if (tkn != null) { return tkn; } // 知らない文字 err = "Unknown char : " + ch1 + " line =" + ln.ToString() + " col = " + col.ToString(); return null; }
static Scene LoadScene(Token[] tokens, ref int n) { var scene = new Scene(); while (true) { if (tokens[n].Kind == TokenKind.Letter && tokens[n].Letter == "pos") { scene.Position.X = (float)tokens[n + 1].Digit; scene.Position.Y = (float)tokens[n + 2].Digit; scene.Position.Z = (float)tokens[n + 3].Digit; n += 4; } if (tokens[n].Kind == TokenKind.Letter && tokens[n].Letter == "dirlights") { while (true) { if (tokens[n].Kind == TokenKind.Letter && tokens[n].Letter == "light") { if (tokens[n].Kind == TokenKind.RCurly) { n++; break; } else { n++; } } else if (tokens[n].Kind == TokenKind.RCurly) { n++; break; } else { n++; } } } else if (tokens[n].Kind == TokenKind.RCurly) { n++; break; } else { n++; } } return scene; }
static Material[] LoadMaterials(Token[] tokens, ref int n) { var materials = new Material[(int)tokens[n + 1].Digit]; for (int i = 0; i < materials.Length; i++) { materials[i] = new Material(); } n += 3; for (int index = 0; index < materials.Length; index++) { if (tokens[n].Kind == TokenKind.String) { materials[index].Name = tokens[n].String; n++; } while (true) { if (tokens[n].Kind == TokenKind.String) { break; } else if (tokens[n].Kind == TokenKind.Letter) { var valueName = tokens[n].Letter; n++; // ( n++; int valueCount = 0; while (tokens[n + valueCount].Kind != TokenKind.Rparen) { valueCount++; } if (valueCount == 1 && tokens[n].Kind == TokenKind.String) { materials[index].Paramaters.Add(valueName, tokens[n + 0].String); } else if (valueCount == 1) { materials[index].Paramaters.Add(valueName, new float[] { (float)tokens[n + 0].Digit }); } else if (valueCount == 2) { materials[index].Paramaters.Add(valueName, new float[] { (float)tokens[n + 0].Digit, (float)tokens[n + 1].Digit }); } else if (valueCount == 3) { materials[index].Paramaters.Add(valueName, new float[] { (float)tokens[n + 0].Digit, (float)tokens[n + 1].Digit, (float)tokens[n + 2].Digit }); } else if (valueCount == 4) { materials[index].Paramaters.Add(valueName, new float[] { (float)tokens[n + 0].Digit, (float)tokens[n + 1].Digit, (float)tokens[n + 2].Digit, (float)tokens[n + 3].Digit }); } n += valueCount; // ) n++; } else if (tokens[n].Kind == TokenKind.RCurly) { break; } else { n++; } } } n++; return materials.ToArray(); }
static Object LoadObject(Token[] tokens, ref int n, Material[] materials) { Object obj = new Object(); obj.Name = tokens[n + 1].String; n += 3; while (true) { if (tokens[n].Kind == TokenKind.Letter && tokens[n].Letter == "facet") { obj.Facet = (float)tokens[n + 1].Digit; n += 2; } else if (tokens[n].Kind == TokenKind.Letter && tokens[n].Letter == "vertex") { obj.Vertexes = new Vector3D[(int)tokens[n + 1].Digit]; n += 3; for (int vind = 0; vind < obj.Vertexes.Length; vind++) { obj.Vertexes[vind].X = (float)tokens[n + 0].Digit; obj.Vertexes[vind].Y = (float)tokens[n + 1].Digit; obj.Vertexes[vind].Z = (float)tokens[n + 2].Digit; n += 3; } n += 1; } else if (tokens[n].Kind == TokenKind.Letter && tokens[n].Letter == "face") { obj.Faces = new Face[(int)tokens[n + 1].Digit]; for (int i = 0; i < obj.Faces.Length; i++) { obj.Faces[i] = new Face(); } n += 3; for (int find = 0; find < obj.Faces.Length; find++) { int count = (int)tokens[n + 0].Digit; obj.Faces[find].Indexes = new int[count]; obj.Faces[find].UV = new float[count * 2]; obj.Faces[find].Colors = new Color[count]; for (int fvind = 0; fvind < count; fvind++) { obj.Faces[find].Colors[fvind] = new Color(1.0f, 1.0f, 1.0f, 1.0f); } n += 1; while (true) { if (tokens[n].Kind == TokenKind.Digit) { break; } else if (tokens[n].Kind == TokenKind.Letter && tokens[n].Letter == "V") { n += 2; for (int c = 0; c < count; c++) { obj.Faces[find].Indexes[c] = (int)tokens[n + c].Digit; } n += count; n += 1; } else if (tokens[n].Kind == TokenKind.Letter && tokens[n].Letter == "M") { n += 2; obj.Faces[find].MaterialIndex = (int)tokens[n + 0].Digit; n += 1; n += 1; } else if (tokens[n].Kind == TokenKind.Letter && tokens[n].Letter == "UV") { n += 2; for (int c = 0; c < count; c++) { obj.Faces[find].UV[c * 2 + 0] = (float)tokens[n + c * 2 + 0].Digit; obj.Faces[find].UV[c * 2 + 1] = (float)tokens[n + c * 2 + 1].Digit; } n += count * 2; n += 1; } else if (tokens[n].Kind == TokenKind.Letter && tokens[n].Letter == "COL") { n += 2; for (int c = 0; c < count; c++) { var color = (UInt64)tokens[n + c].Digit; var r = (color & 0x000000FF) >> 0; var g = (color & 0x0000FF00) >> 8; var b = (color & 0x00FF0000) >> 16; var a = (color & 0xFF000000) >> 24; obj.Faces[find].Colors[c] = new Color(r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f); } n += count; n += 1; } else if (tokens[n].Kind == TokenKind.RCurly) { break; } else { n++; } } } n += 1; } else if (tokens[n].Kind == TokenKind.RCurly) { n++; break; } else { n++; } } return obj; }