< Summary

Line coverage
99%
Covered lines: 545
Uncovered lines: 1
Coverable lines: 546
Total lines: 1401
Line coverage: 99.8%
Branch coverage
99%
Covered branches: 523
Total branches: 524
Branch coverage: 99.8%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
MoveNextSkipEmpty(...)75%4475%
MoveNextSkipEmpty(...)75%4475%
GetNextValue(...)100%11100%
GetNextValue(...)100%11100%
FloatParse(...)100%11100%
IntParse(...)100%11100%
LongParse(...)100%11100%
FromStream(...)100%388388100%
ParseTriplet(...)100%3838100%
ParseCurveIndex(...)100%88100%
ParseCurveIndex(...)100%88100%
ParseCurveIndex(...)100%66100%
ParseCurveIndex(...)100%66100%
ParseFreeFormType(...)100%1818100%
ParseFreeFormType(...)100%1818100%
ParseSurfaceConnection(...)100%2020100%
ParseSurfaceConnection(...)100%2020100%
ParseGroupName(...)100%1010100%
ParseGroupName(...)100%1010100%
ParseApproximationTechnique(...)100%3232100%
ParseApproximationTechnique(...)100%3232100%

File(s)

https://raw.githubusercontent.com/JeremyAnsel/JeremyAnsel.Media.WavefrontObj/7b5b951766c69f14731a856f32198cdbf1fc6847/JeremyAnsel.Media.WavefrontObj/JeremyAnsel.Media.WavefrontObj/ObjFileReader9.cs

#LineLine coverage
 1// <copyright file="ObjFileReader9.cs" company="Jérémy Ansel">
 2// Copyright (c) 2017, 2019 Jérémy Ansel
 3// </copyright>
 4// <license>
 5// Licensed under the MIT license. See LICENSE.txt
 6// </license>
 7
 8#if NET6_0_OR_GREATER
 9
 10using System.Diagnostics.CodeAnalysis;
 11using System.Globalization;
 12using System.Text;
 13
 14#if NET9_0_OR_GREATER
 15using SpanSplitEnumerator = System.MemoryExtensions.SpanSplitEnumerator<char>;
 16#else
 17using SpanSplitEnumerator = Polyfills.Polyfill.SpanSplitEnumerator<char>;
 18#endif
 19
 20namespace JeremyAnsel.Media.WavefrontObj
 21{
 22    internal static class ObjFileReader9
 23    {
 24        private static void MoveNextSkipEmpty(ref SpanSplitEnumerator values)
 25        {
 682526            while (values.MoveNext())
 27            {
 682528                if (values.Current.Start.Value != values.Current.End.Value)
 29                {
 678030                    return;
 31                }
 32            }
 033        }
 34
 35        private static ReadOnlySpan<char> GetNextValue(ref ReadOnlySpan<char> currentLine, ref SpanSplitEnumerator value
 36        {
 462337            MoveNextSkipEmpty(ref values);
 462338            return currentLine[values.Current];
 39        }
 40
 41        private static float FloatParse(ReadOnlySpan<char> s)
 42        {
 298243            return float.Parse(s, NumberStyles.Float, CultureInfo.InvariantCulture);
 44        }
 45
 46        private static int IntParse(ReadOnlySpan<char> s)
 47        {
 110748            return int.Parse(s, NumberStyles.Integer, CultureInfo.InvariantCulture);
 49        }
 50
 51        private static long LongParse(ReadOnlySpan<char> s)
 52        {
 1853            return long.Parse(s, NumberStyles.Integer, CultureInfo.InvariantCulture);
 54        }
 55
 56        [SuppressMessage("Globalization", "CA1303:Ne pas passer de littéraux en paramètres localisés", Justification = "
 57        public static ObjFile FromStream(Stream? stream, ObjFileReaderSettings settings)
 58        {
 85859            if (stream == null)
 60            {
 361                throw new ArgumentNullException(nameof(stream));
 62            }
 63
 85564            var obj = new ObjFile();
 85565            var context = new ObjFileReaderContext(obj, settings);
 85566            var lineReader = new LineReader9();
 67
 85568            int valueBufferSize = 16;
 85569            Span<char> valueBuffer = stackalloc char[valueBufferSize];
 70
 552071            foreach (var currentLineString in lineReader.Read9(stream))
 72            {
 215773                ReadOnlySpan<char> currentLine = currentLineString.Buffer.AsSpan()[..currentLineString.Length];
 74
 215775                int valuesCount = 0;
 76
 1948877                foreach (Range range in currentLine.SplitAny(LineReader9.LineSeparators))
 78                {
 758779                    if (currentLine[range].Length == 0)
 80                    {
 81                        continue;
 82                    }
 83
 750084                    valuesCount++;
 85                }
 86
 215787                SpanSplitEnumerator values = currentLine.SplitAny(LineReader9.LineSeparators);
 88
 215789                MoveNextSkipEmpty(ref values);
 90
 215791                if (values.Current.End.Value - values.Current.Start.Value > valueBufferSize)
 92                {
 93                    continue;
 94                }
 95
 215496                ReadOnlySpan<char> value0 = currentLine[values.Current];
 215497                int value0Length = value0.ToLowerInvariant(valueBuffer);
 98
 99                //if (value0Length == -1)
 100                //{
 101                //    throw new InvalidDataException("the buffer is too small");
 102                //}
 103
 2154104                switch (valueBuffer[..value0Length])
 105                {
 106                    case "v":
 107                        {
 507108                            if (valuesCount < 4)
 109                            {
 9110                                throw new InvalidDataException("A v statement must specify at least 3 values.");
 111                            }
 112
 498113                            float x = FloatParse(GetNextValue(ref currentLine, ref values));
 498114                            float y = FloatParse(GetNextValue(ref currentLine, ref values));
 498115                            float z = FloatParse(GetNextValue(ref currentLine, ref values));
 498116                            float w = 1.0f;
 498117                            bool hasColor = false;
 498118                            float r = 0.0f;
 498119                            float g = 0.0f;
 498120                            float b = 0.0f;
 498121                            float a = 1.0f;
 122
 498123                            if (valuesCount == 4 || valuesCount == 5)
 124                            {
 486125                                if (valuesCount == 5)
 126                                {
 3127                                    w = FloatParse(GetNextValue(ref currentLine, ref values));
 128                                }
 129                            }
 12130                            else if (valuesCount == 7 || valuesCount == 8)
 131                            {
 6132                                hasColor = true;
 6133                                r = FloatParse(GetNextValue(ref currentLine, ref values));
 6134                                g = FloatParse(GetNextValue(ref currentLine, ref values));
 6135                                b = FloatParse(GetNextValue(ref currentLine, ref values));
 136
 6137                                if (valuesCount == 8)
 138                                {
 3139                                    a = FloatParse(GetNextValue(ref currentLine, ref values));
 140                                }
 141                            }
 142                            else
 143                            {
 6144                                throw new InvalidDataException("A v statement has too many values.");
 145                            }
 146
 492147                            var v = new ObjVertex();
 492148                            v.Position = new ObjVector4(x, y, z, w);
 149
 492150                            if (hasColor)
 151                            {
 6152                                v.Color = new ObjVector4(r, g, b, a);
 153                            }
 154
 492155                            obj.Vertices.Add(v);
 492156                            break;
 157                        }
 158
 159                    case "vp":
 160                        {
 180161                            if (valuesCount < 2)
 162                            {
 3163                                throw new InvalidDataException("A vp statement must specify at least 1 value.");
 164                            }
 165
 177166                            var v = new ObjVector3();
 177167                            v.X = FloatParse(GetNextValue(ref currentLine, ref values));
 168
 177169                            if (valuesCount == 2)
 170                            {
 3171                                v.Y = 0.0f;
 3172                                v.Z = 1.0f;
 173                            }
 174174                            else if (valuesCount == 3)
 175                            {
 3176                                v.Y = FloatParse(GetNextValue(ref currentLine, ref values));
 3177                                v.Z = 1.0f;
 178                            }
 171179                            else if (valuesCount == 4)
 180                            {
 168181                                v.Y = FloatParse(GetNextValue(ref currentLine, ref values));
 168182                                v.Z = FloatParse(GetNextValue(ref currentLine, ref values));
 183                            }
 184                            else
 185                            {
 3186                                throw new InvalidDataException("A vp statement has too many values.");
 187                            }
 188
 174189                            obj.ParameterSpaceVertices.Add(v);
 174190                            break;
 191                        }
 192
 193                    case "vn":
 194                        {
 36195                            if (valuesCount < 4)
 196                            {
 9197                                throw new InvalidDataException("A vn statement must specify 3 values.");
 198                            }
 199
 27200                            if (valuesCount != 4)
 201                            {
 3202                                throw new InvalidDataException("A vn statement has too many values.");
 203                            }
 204
 24205                            var v = new ObjVector3();
 24206                            v.X = FloatParse(GetNextValue(ref currentLine, ref values));
 24207                            v.Y = FloatParse(GetNextValue(ref currentLine, ref values));
 24208                            v.Z = FloatParse(GetNextValue(ref currentLine, ref values));
 209
 24210                            obj.VertexNormals.Add(v);
 24211                            break;
 212                        }
 213
 214                    case "vt":
 215                        {
 33216                            if (valuesCount < 2)
 217                            {
 3218                                throw new InvalidDataException("A vt statement must specify at least 1 value.");
 219                            }
 220
 30221                            var v = new ObjVector3();
 30222                            v.X = FloatParse(GetNextValue(ref currentLine, ref values));
 223
 30224                            if (valuesCount == 2)
 225                            {
 21226                                v.Y = 0.0f;
 21227                                v.Z = 0.0f;
 228                            }
 9229                            else if (valuesCount == 3)
 230                            {
 3231                                v.Y = FloatParse(GetNextValue(ref currentLine, ref values));
 3232                                v.Z = 0.0f;
 233                            }
 6234                            else if (valuesCount == 4)
 235                            {
 3236                                v.Y = FloatParse(GetNextValue(ref currentLine, ref values));
 3237                                v.Z = FloatParse(GetNextValue(ref currentLine, ref values));
 238                            }
 239                            else
 240                            {
 3241                                throw new InvalidDataException("A vt statement has too many values.");
 242                            }
 243
 27244                            obj.TextureVertices.Add(v);
 27245                            break;
 246                        }
 247
 248                    case "cstype":
 45249                        ParseFreeFormType(context, ref value0, ref currentLine, ref values, valuesCount);
 30250                        break;
 251
 252                    case "deg":
 21253                        if (valuesCount < 2)
 254                        {
 3255                            throw new InvalidDataException("A deg statement must specify at least 1 value.");
 256                        }
 257
 18258                        if (valuesCount == 2)
 259                        {
 3260                            context.DegreeU = IntParse(GetNextValue(ref currentLine, ref values));
 3261                            context.DegreeV = 0;
 262                        }
 15263                        else if (valuesCount == 3)
 264                        {
 12265                            context.DegreeU = IntParse(GetNextValue(ref currentLine, ref values));
 12266                            context.DegreeV = IntParse(GetNextValue(ref currentLine, ref values));
 267                        }
 268                        else
 269                        {
 3270                            throw new InvalidDataException("A deg statement has too many values.");
 271                        }
 272
 273                        break;
 274
 275                    case "bmat":
 276                        {
 15277                            if (valuesCount < 2)
 278                            {
 3279                                throw new InvalidDataException("A bmat statement must specify a direction.");
 280                            }
 281
 282                            int d;
 12283                            var value1 = GetNextValue(ref currentLine, ref values);
 284
 12285                            if (value1.Equals("u", StringComparison.OrdinalIgnoreCase))
 286                            {
 6287                                d = 1;
 288                            }
 6289                            else if (value1.Equals("v", StringComparison.OrdinalIgnoreCase))
 290                            {
 3291                                d = 2;
 292                            }
 293                            else
 294                            {
 3295                                throw new InvalidDataException("A bmat statement has an unknown direction.");
 296                            }
 297
 9298                            int count = (context.DegreeU + 1) * (context.DegreeV + 1);
 299
 9300                            if (valuesCount != count + 2)
 301                            {
 3302                                throw new InvalidDataException("A bmat statement has too many or too few values.");
 303                            }
 304
 6305                            var matrix = new float[count];
 306
 156307                            for (int i = 0; i < count; i++)
 308                            {
 72309                                matrix[i] = FloatParse(GetNextValue(ref currentLine, ref values));
 310                            }
 311
 312                            switch (d)
 313                            {
 314                                case 1:
 3315                                    context.BasicMatrixU = matrix;
 3316                                    break;
 317
 318                                case 2:
 3319                                    context.BasicMatrixV = matrix;
 3320                                    break;
 321                            }
 322
 323                            break;
 324                        }
 325
 326                    case "step":
 12327                        if (valuesCount < 2)
 328                        {
 3329                            throw new InvalidDataException("A step statement must specify at least 1 value.");
 330                        }
 331
 9332                        if (valuesCount == 2)
 333                        {
 3334                            context.StepU = FloatParse(GetNextValue(ref currentLine, ref values));
 3335                            context.StepV = 1.0f;
 336                        }
 6337                        else if (valuesCount == 3)
 338                        {
 3339                            context.StepU = FloatParse(GetNextValue(ref currentLine, ref values));
 3340                            context.StepV = FloatParse(GetNextValue(ref currentLine, ref values));
 341                        }
 342                        else
 343                        {
 3344                            throw new InvalidDataException("A step statement has too many values.");
 345                        }
 346
 347                        break;
 348
 349                    case "p":
 350                        {
 105351                            if (valuesCount < 2)
 352                            {
 3353                                throw new InvalidDataException("A p statement must specify at least 1 value.");
 354                            }
 355
 102356                            var point = new ObjPoint();
 357
 366358                            for (int i = 1; i < valuesCount; i++)
 359                            {
 108360                                point.Vertices.Add(ParseTriplet(obj, GetNextValue(ref currentLine, ref values)));
 361                            }
 362
 75363                            context.ApplyAttributesToElement(point);
 75364                            context.ApplyAttributesToPolygonalElement(point);
 365
 75366                            obj.Points.Add(point);
 367
 300368                            foreach (var group in context.GetCurrentGroups())
 369                            {
 75370                                group.Points.Add(point);
 371                            }
 372
 373                            break;
 374                        }
 375
 376                    case "l":
 377                        {
 12378                            if (valuesCount < 3)
 379                            {
 6380                                throw new InvalidDataException("A l statement must specify at least 2 values.");
 381                            }
 382
 6383                            var line = new ObjLine();
 384
 48385                            for (int i = 1; i < valuesCount; i++)
 386                            {
 18387                                line.Vertices.Add(ParseTriplet(obj, GetNextValue(ref currentLine, ref values)));
 388                            }
 389
 6390                            context.ApplyAttributesToElement(line);
 6391                            context.ApplyAttributesToPolygonalElement(line);
 392
 6393                            obj.Lines.Add(line);
 394
 24395                            foreach (var group in context.GetCurrentGroups())
 396                            {
 6397                                group.Lines.Add(line);
 398                            }
 399
 400                            break;
 401                        }
 402
 403                    case "f":
 404                    case "fo":
 405                        {
 30406                            if (valuesCount < 4)
 407                            {
 18408                                throw new InvalidDataException("A f statement must specify at least 3 values.");
 409                            }
 410
 12411                            var face = new ObjFace();
 412
 144413                            for (int i = 1; i < valuesCount; i++)
 414                            {
 60415                                face.Vertices.Add(ParseTriplet(obj, GetNextValue(ref currentLine, ref values)));
 416                            }
 417
 12418                            context.ApplyAttributesToElement(face);
 12419                            context.ApplyAttributesToPolygonalElement(face);
 420
 12421                            obj.Faces.Add(face);
 422
 48423                            foreach (var group in context.GetCurrentGroups())
 424                            {
 12425                                group.Faces.Add(face);
 426                            }
 427
 428                            break;
 429                        }
 430
 431                    case "curv":
 432                        {
 135433                            if (valuesCount < 5)
 434                            {
 12435                                throw new InvalidDataException("A curv statement must specify at least 4 values.");
 436                            }
 437
 123438                            var curve = new ObjCurve();
 439
 123440                            curve.StartParameter = FloatParse(GetNextValue(ref currentLine, ref values));
 123441                            curve.EndParameter = FloatParse(GetNextValue(ref currentLine, ref values));
 442
 714443                            for (int i = 3; i < valuesCount; i++)
 444                            {
 243445                                int v = IntParse(GetNextValue(ref currentLine, ref values));
 446
 243447                                if (v == 0)
 448                                {
 3449                                    throw new InvalidDataException("A curv statement contains an invalid vertex index.")
 450                                }
 451
 240452                                if (v < 0)
 453                                {
 3454                                    v = obj.Vertices.Count + v + 1;
 455                                }
 456
 240457                                if (v <= 0 || v > obj.Vertices.Count)
 458                                {
 6459                                    throw new IndexOutOfRangeException();
 460                                }
 461
 234462                                curve.Vertices.Add(v);
 463                            }
 464
 114465                            context.ApplyAttributesToElement(curve);
 114466                            context.ApplyAttributesToFreeFormElement(curve);
 114467                            context.CurrentFreeFormElement = curve;
 468
 114469                            obj.Curves.Add(curve);
 470
 456471                            foreach (var group in context.GetCurrentGroups())
 472                            {
 114473                                group.Curves.Add(curve);
 474                            }
 475
 476                            break;
 477                        }
 478
 479                    case "curv2":
 480                        {
 183481                            if (valuesCount < 3)
 482                            {
 6483                                throw new InvalidDataException("A curv2 statement must specify at least 2 values.");
 484                            }
 485
 177486                            var curve = new ObjCurve2D();
 487
 1038488                            for (int i = 1; i < valuesCount; i++)
 489                            {
 351490                                int vp = IntParse(GetNextValue(ref currentLine, ref values));
 491
 351492                                if (vp == 0)
 493                                {
 3494                                    throw new InvalidDataException("A curv2 statement contains an invalid parameter spac
 495                                }
 496
 348497                                if (vp < 0)
 498                                {
 3499                                    vp = obj.ParameterSpaceVertices.Count + vp + 1;
 500                                }
 501
 348502                                if (vp <= 0 || vp > obj.ParameterSpaceVertices.Count)
 503                                {
 6504                                    throw new IndexOutOfRangeException();
 505                                }
 506
 342507                                curve.ParameterSpaceVertices.Add(vp);
 508                            }
 509
 168510                            context.ApplyAttributesToElement(curve);
 168511                            context.ApplyAttributesToFreeFormElement(curve);
 168512                            context.CurrentFreeFormElement = curve;
 513
 168514                            obj.Curves2D.Add(curve);
 515
 672516                            foreach (var group in context.GetCurrentGroups())
 517                            {
 168518                                group.Curves2D.Add(curve);
 519                            }
 520
 521                            break;
 522                        }
 523
 524                    case "surf":
 525                        {
 78526                            if (valuesCount < 6)
 527                            {
 18528                                throw new InvalidDataException("A surf statement must specify at least 5 values.");
 529                            }
 530
 60531                            var surface = new ObjSurface();
 532
 60533                            surface.StartParameterU = FloatParse(GetNextValue(ref currentLine, ref values));
 60534                            surface.EndParameterU = FloatParse(GetNextValue(ref currentLine, ref values));
 60535                            surface.StartParameterV = FloatParse(GetNextValue(ref currentLine, ref values));
 60536                            surface.EndParameterV = FloatParse(GetNextValue(ref currentLine, ref values));
 537
 252538                            for (int i = 5; i < valuesCount; i++)
 539                            {
 72540                                surface.Vertices.Add(ParseTriplet(obj, GetNextValue(ref currentLine, ref values)));
 541                            }
 542
 54543                            context.ApplyAttributesToElement(surface);
 54544                            context.ApplyAttributesToFreeFormElement(surface);
 54545                            context.CurrentFreeFormElement = surface;
 546
 54547                            obj.Surfaces.Add(surface);
 548
 216549                            foreach (var group in context.GetCurrentGroups())
 550                            {
 54551                                group.Surfaces.Add(surface);
 552                            }
 553
 554                            break;
 555                        }
 556
 557                    case "parm":
 558                        {
 21559                            if (context.CurrentFreeFormElement == null)
 560                            {
 561                                break;
 562                            }
 563
 18564                            if (valuesCount < 4)
 565                            {
 9566                                throw new InvalidDataException("A parm statement must specify at least 3 values.");
 567                            }
 568
 569                            List<float> parameters;
 9570                            var value1 = GetNextValue(ref currentLine, ref values);
 571
 9572                            if (value1.Equals("u", StringComparison.OrdinalIgnoreCase))
 573                            {
 3574                                parameters = context.CurrentFreeFormElement.ParametersU;
 575                            }
 6576                            else if (value1.Equals("v", StringComparison.OrdinalIgnoreCase))
 577                            {
 3578                                parameters = context.CurrentFreeFormElement.ParametersV;
 579                            }
 580                            else
 581                            {
 3582                                throw new InvalidDataException("A parm statement has an unknown direction.");
 583                            }
 584
 48585                            for (int i = 2; i < valuesCount; i++)
 586                            {
 18587                                parameters.Add(FloatParse(GetNextValue(ref currentLine, ref values)));
 588                            }
 589
 6590                            break;
 591                        }
 592
 593                    case "trim":
 30594                        if (context.CurrentFreeFormElement == null)
 595                        {
 596                            break;
 597                        }
 598
 27599                        ParseCurveIndex(context.CurrentFreeFormElement.OuterTrimmingCurves, obj, value0, ref currentLine
 3600                        break;
 601
 602                    case "hole":
 30603                        if (context.CurrentFreeFormElement == null)
 604                        {
 605                            break;
 606                        }
 607
 27608                        ParseCurveIndex(context.CurrentFreeFormElement.InnerTrimmingCurves, obj, value0, ref currentLine
 3609                        break;
 610
 611                    case "scrv":
 30612                        if (context.CurrentFreeFormElement == null)
 613                        {
 614                            break;
 615                        }
 616
 27617                        ParseCurveIndex(context.CurrentFreeFormElement.SequenceCurves, obj, value0, ref currentLine, ref
 3618                        break;
 619
 620                    case "sp":
 18621                        if (context.CurrentFreeFormElement == null)
 622                        {
 623                            break;
 624                        }
 625
 15626                        if (valuesCount < 2)
 627                        {
 3628                            throw new InvalidDataException("A sp statement must specify at least 1 value.");
 629                        }
 630
 36631                        for (int i = 1; i < valuesCount; i++)
 632                        {
 15633                            int vp = IntParse(GetNextValue(ref currentLine, ref values));
 634
 15635                            if (vp == 0)
 636                            {
 3637                                throw new InvalidDataException("A sp statement contains an invalid parameter space verte
 638                            }
 639
 12640                            if (vp < 0)
 641                            {
 3642                                vp = obj.ParameterSpaceVertices.Count + vp + 1;
 643                            }
 644
 12645                            if (vp <= 0 || vp > obj.ParameterSpaceVertices.Count)
 646                            {
 6647                                throw new IndexOutOfRangeException();
 648                            }
 649
 6650                            context.CurrentFreeFormElement.SpecialPoints.Add(vp);
 651                        }
 652
 3653                        break;
 654
 655                    case "end":
 18656                        context.CurrentFreeFormElement = null;
 18657                        break;
 658
 659                    case "con":
 66660                        ParseSurfaceConnection(obj, value0, ref currentLine, ref values, valuesCount);
 3661                        break;
 662
 663                    case "g":
 78664                        ParseGroupName(context, value0, ref currentLine, ref values, valuesCount);
 78665                        break;
 666
 667                    case "s":
 668                        {
 27669                            if (valuesCount < 2)
 670                            {
 3671                                throw new InvalidDataException("A s statement must specify a value.");
 672                            }
 673
 24674                            if (valuesCount != 2)
 675                            {
 3676                                throw new InvalidDataException("A s statement has too many values.");
 677                            }
 678
 21679                            var value1 = GetNextValue(ref currentLine, ref values);
 680
 21681                            if (value1.Equals("off", StringComparison.OrdinalIgnoreCase))
 682                            {
 3683                                context.SmoothingGroupNumber = 0;
 684                            }
 685                            else
 686                            {
 18687                                context.SmoothingGroupNumber = LongParse(value1);
 688                            }
 689
 18690                            break;
 691                        }
 692
 693                    case "mg":
 694                        {
 30695                            if (valuesCount < 2)
 696                            {
 3697                                throw new InvalidDataException("A mg statement must specify a value.");
 698                            }
 699
 27700                            var value1 = GetNextValue(ref currentLine, ref values);
 701
 27702                            if (value1.Equals("off", StringComparison.OrdinalIgnoreCase))
 703                            {
 3704                                context.MergingGroupNumber = 0;
 705                            }
 706                            else
 707                            {
 24708                                context.MergingGroupNumber = IntParse(value1);
 709                            }
 710
 27711                            if (context.MergingGroupNumber == 0)
 712                            {
 9713                                if (valuesCount > 3)
 714                                {
 3715                                    throw new InvalidDataException("A mg statement has too many values.");
 716                                }
 717                            }
 718                            else
 719                            {
 18720                                if (valuesCount != 3)
 721                                {
 6722                                    throw new InvalidDataException("A mg statement has too many or too few values.");
 723                                }
 724
 12725                                float res = FloatParse(GetNextValue(ref currentLine, ref values));
 726
 12727                                obj.MergingGroupResolutions[context.MergingGroupNumber] = res;
 728                            }
 729
 12730                            break;
 731                        }
 732
 733                    case "o":
 39734                        if (settings.HandleObjectNamesAsGroup)
 735                        {
 9736                            ParseGroupName(context, value0, ref currentLine, ref values, valuesCount);
 9737                            break;
 738                        }
 739
 30740                        if (valuesCount == 1)
 741                        {
 3742                            context.ObjectName = null;
 3743                            break;
 744                        }
 745
 27746                        if (valuesCount != 2)
 747                        {
 3748                            throw new InvalidDataException("A o statement has too many values.");
 749                        }
 750
 24751                        context.ObjectName = GetNextValue(ref currentLine, ref values).ToString();
 24752                        break;
 753
 754                    case "bevel":
 755                        {
 27756                            if (valuesCount < 2)
 757                            {
 3758                                throw new InvalidDataException("A bevel statement must specify a name.");
 759                            }
 760
 24761                            if (valuesCount != 2)
 762                            {
 3763                                throw new InvalidDataException("A bevel statement has too many values.");
 764                            }
 765
 21766                            var value1 = GetNextValue(ref currentLine, ref values);
 767
 21768                            if (value1.Equals("on", StringComparison.OrdinalIgnoreCase))
 769                            {
 15770                                context.IsBevelInterpolationEnabled = true;
 771                            }
 6772                            else if (value1.Equals("off", StringComparison.OrdinalIgnoreCase))
 773                            {
 3774                                context.IsBevelInterpolationEnabled = false;
 775                            }
 776                            else
 777                            {
 3778                                throw new InvalidDataException("A bevel statement must specify on or off.");
 779                            }
 780
 781                            break;
 782                        }
 783
 784                    case "c_interp":
 785                        {
 27786                            if (valuesCount < 2)
 787                            {
 3788                                throw new InvalidDataException("A c_interp statement must specify a name.");
 789                            }
 790
 24791                            if (valuesCount != 2)
 792                            {
 3793                                throw new InvalidDataException("A c_interp statement has too many values.");
 794                            }
 795
 21796                            var value1 = GetNextValue(ref currentLine, ref values);
 797
 21798                            if (value1.Equals("on", StringComparison.OrdinalIgnoreCase))
 799                            {
 15800                                context.IsColorInterpolationEnabled = true;
 801                            }
 6802                            else if (value1.Equals("off", StringComparison.OrdinalIgnoreCase))
 803                            {
 3804                                context.IsColorInterpolationEnabled = false;
 805                            }
 806                            else
 807                            {
 3808                                throw new InvalidDataException("A c_interp statement must specify on or off.");
 809                            }
 810
 811                            break;
 812                        }
 813
 814                    case "d_interp":
 815                        {
 27816                            if (valuesCount < 2)
 817                            {
 3818                                throw new InvalidDataException("A d_interp statement must specify a name.");
 819                            }
 820
 24821                            if (valuesCount != 2)
 822                            {
 3823                                throw new InvalidDataException("A d_interp statement has too many values.");
 824                            }
 825
 21826                            var value1 = GetNextValue(ref currentLine, ref values);
 827
 21828                            if (value1.Equals("on", StringComparison.OrdinalIgnoreCase))
 829                            {
 15830                                context.IsDissolveInterpolationEnabled = true;
 831                            }
 6832                            else if (value1.Equals("off", StringComparison.OrdinalIgnoreCase))
 833                            {
 3834                                context.IsDissolveInterpolationEnabled = false;
 835                            }
 836                            else
 837                            {
 3838                                throw new InvalidDataException("A d_interp statement must specify on or off.");
 839                            }
 840
 841                            break;
 842                        }
 843
 844                    case "lod":
 30845                        if (valuesCount < 2)
 846                        {
 3847                            throw new InvalidDataException("A lod statement must specify a value.");
 848                        }
 849
 27850                        if (valuesCount != 2)
 851                        {
 3852                            throw new InvalidDataException("A lod statement has too many values.");
 853                        }
 854
 24855                        context.LevelOfDetail = IntParse(GetNextValue(ref currentLine, ref values));
 24856                        break;
 857
 858                    case "maplib":
 6859                        if (valuesCount < 2)
 860                        {
 3861                            throw new InvalidDataException("A maplib statement must specify a file name.");
 862                        }
 863
 18864                        for (int i = 1; i < valuesCount; i++)
 865                        {
 6866                            obj.MapLibraries.Add(GetNextValue(ref currentLine, ref values).ToString());
 867                        }
 868
 3869                        break;
 870
 871                    case "mtllib":
 872                        {
 18873                            if (valuesCount < 2)
 874                            {
 3875                                throw new InvalidDataException("A mtllib statement must specify a file name.");
 876                            }
 877
 15878                            if (settings.KeepWhitespacesOfMtlLibReferences)
 879                            {
 6880                                obj.MaterialLibraries.Add(new string(currentLine[7..]).Trim());
 881                            }
 882                            else
 883                            {
 9884                                var sb = new StringBuilder();
 885
 9886                                sb.Append(GetNextValue(ref currentLine, ref values));
 887
 60888                                for (int i = 2; i < valuesCount; i++)
 889                                {
 21890                                    sb.Append(' ');
 21891                                    sb.Append(GetNextValue(ref currentLine, ref values));
 892                                }
 893
 9894                                obj.MaterialLibraries.Add(sb.ToString());
 895                            }
 896
 9897                            break;
 898                        }
 899
 900                    case "usemap":
 901                        {
 33902                            if (valuesCount < 2)
 903                            {
 3904                                throw new InvalidDataException("A usemap statement must specify a value.");
 905                            }
 906
 30907                            if (valuesCount != 2)
 908                            {
 3909                                throw new InvalidDataException("A usemap statement has too many values.");
 910                            }
 911
 27912                            var value1 = GetNextValue(ref currentLine, ref values);
 913
 27914                            if (value1.Equals("off", StringComparison.OrdinalIgnoreCase))
 915                            {
 3916                                context.MapName = null;
 917                            }
 918                            else
 919                            {
 24920                                context.MapName = value1.ToString();
 921                            }
 922
 24923                            break;
 924                        }
 925
 926                    case "usemtl":
 927                        {
 36928                            if (valuesCount < 2)
 929                            {
 3930                                throw new InvalidDataException("A usemtl statement must specify a value.");
 931                            }
 932
 33933                            var value1 = GetNextValue(ref currentLine, ref values);
 934
 33935                            if (value1.Equals("off", StringComparison.OrdinalIgnoreCase))
 936                            {
 6937                                if (valuesCount != 2)
 938                                {
 3939                                    throw new InvalidDataException("A usemtl statement has too many values.");
 940                                }
 941
 3942                                context.MaterialName = null;
 943                            }
 944                            else
 945                            {
 27946                                var sb = new StringBuilder();
 947
 27948                                sb.Append(value1);
 949
 84950                                for (int i = 2; i < valuesCount; i++)
 951                                {
 15952                                    sb.Append(' ');
 15953                                    sb.Append(GetNextValue(ref currentLine, ref values));
 954                                }
 955
 27956                                context.MaterialName = sb.ToString();
 957                            }
 958
 27959                            break;
 960                        }
 961
 962                    case "shadow_obj":
 963                        {
 18964                            if (valuesCount < 2)
 965                            {
 3966                                throw new InvalidDataException("A shadow_obj statement must specify a file name.");
 967                            }
 968
 15969                            var sb = new StringBuilder();
 970
 15971                            sb.Append(GetNextValue(ref currentLine, ref values));
 972
 36973                            for (int i = 2; i < valuesCount; i++)
 974                            {
 3975                                sb.Append(' ');
 3976                                sb.Append(GetNextValue(ref currentLine, ref values));
 977                            }
 978
 15979                            obj.ShadowObjectFileName = sb.ToString();
 15980                            break;
 981                        }
 982
 983                    case "trace_obj":
 984                        {
 12985                            if (valuesCount < 2)
 986                            {
 3987                                throw new InvalidDataException("A trace_obj statement must specify a file name.");
 988                            }
 989
 9990                            var sb = new StringBuilder();
 991
 9992                            sb.Append(GetNextValue(ref currentLine, ref values));
 993
 24994                            for (int i = 2; i < valuesCount; i++)
 995                            {
 3996                                sb.Append(' ');
 3997                                sb.Append(GetNextValue(ref currentLine, ref values));
 998                            }
 999
 91000                            obj.TraceObjectFileName = sb.ToString();
 91001                            break;
 1002                        }
 1003
 1004                    case "ctech":
 541005                        context.CurveApproximationTechnique = ParseApproximationTechnique(value0, ref currentLine, ref v
 271006                        break;
 1007
 1008                    case "stech":
 661009                        context.SurfaceApproximationTechnique = ParseApproximationTechnique(value0, ref currentLine, ref
 301010                        break;
 1011
 1012                    case "bsp":
 1013                    case "bzp":
 1014                    case "cdc":
 1015                    case "cdp":
 1016                    case "res":
 151017                        throw new NotImplementedException(string.Concat(value0.ToString(), " statement have been replace
 1018                }
 1019            }
 1020
 3511021            obj.HeaderText = string.Join("\n", lineReader.HeaderTextLines.ToArray());
 1022
 3511023            return obj;
 1024        }
 1025
 1026        [SuppressMessage("Globalization", "CA1303:Ne pas passer de littéraux en paramètres localisés", Justification = "
 1027        private static ObjTriplet ParseTriplet(ObjFile obj, ReadOnlySpan<char> value)
 1028        {
 2581029            int valuesCount = 0;
 1030
 11341031            foreach (Range range in value.Split('/'))
 1032            {
 3091033                valuesCount++;
 1034            }
 1035
 2581036            var values = value.Split('/');
 1037
 2581038            if (valuesCount > 3)
 1039            {
 31040                throw new InvalidDataException("A triplet has too many values.");
 1041            }
 1042
 2551043            values.MoveNext();
 2551044            int v = value[values.Current].Length != 0 ? IntParse(value[values.Current]) : 0;
 1045
 2551046            if (v == 0)
 1047            {
 61048                throw new InvalidDataException("A triplet must specify a vertex index.");
 1049            }
 1050
 2491051            if (v < 0)
 1052            {
 61053                v = obj.Vertices.Count + v + 1;
 1054            }
 1055
 2491056            if (v <= 0 || v > obj.Vertices.Count)
 1057            {
 121058                throw new IndexOutOfRangeException();
 1059            }
 1060
 2371061            values.MoveNext();
 2371062            int vt = valuesCount > 1 && value[values.Current].Length != 0 ? IntParse(value[values.Current]) : 0;
 1063
 2371064            if (vt != 0)
 1065            {
 121066                if (vt < 0)
 1067                {
 31068                    vt = obj.TextureVertices.Count + vt + 1;
 1069                }
 1070
 121071                if (vt <= 0 || vt > obj.TextureVertices.Count)
 1072                {
 61073                    throw new IndexOutOfRangeException();
 1074                }
 1075            }
 1076
 2311077            values.MoveNext();
 2311078            int vn = valuesCount > 2 && value[values.Current].Length != 0 ? IntParse(value[values.Current]) : 0;
 1079
 2311080            if (vn != 0)
 1081            {
 121082                if (vn < 0)
 1083                {
 31084                    vn = obj.VertexNormals.Count + vn + 1;
 1085                }
 1086
 121087                if (vn <= 0 || vn > obj.VertexNormals.Count)
 1088                {
 61089                    throw new IndexOutOfRangeException();
 1090                }
 1091            }
 1092
 2251093            return new ObjTriplet(v, vt, vn);
 1094        }
 1095
 1096        [SuppressMessage("Globalization", "CA1303:Ne pas passer de littéraux en paramètres localisés", Justification = "
 1097        private static ObjCurveIndex ParseCurveIndex(ObjFile obj, ref ReadOnlySpan<char> currentLine, ref SpanSplitEnume
 1098        {
 871099            float start = FloatParse(GetNextValue(ref currentLine, ref values));
 871100            float end = FloatParse(GetNextValue(ref currentLine, ref values));
 871101            int curve2D = IntParse(GetNextValue(ref currentLine, ref values));
 1102
 871103            if (curve2D == 0)
 1104            {
 151105                throw new InvalidDataException("A curve index must specify an index.");
 1106            }
 1107
 721108            if (curve2D < 0)
 1109            {
 151110                curve2D = obj.Curves2D.Count + curve2D + 1;
 1111            }
 1112
 721113            if (curve2D <= 0 || curve2D > obj.Curves2D.Count)
 1114            {
 301115                throw new IndexOutOfRangeException();
 1116            }
 1117
 421118            return new ObjCurveIndex(start, end, curve2D);
 1119        }
 1120
 1121        private static void ParseCurveIndex(List<ObjCurveIndex> curves, ObjFile obj, ReadOnlySpan<char> value0, ref Read
 1122        {
 811123            if (valuesCount < 4)
 1124            {
 271125                throw new InvalidDataException(string.Concat("A ", value0.ToString(), " statement must specify at least 
 1126            }
 1127
 541128            if ((valuesCount - 1) % 3 != 0)
 1129            {
 181130                throw new InvalidDataException(string.Concat("A ", value0.ToString(), " statement has too many values.")
 1131            }
 1132
 1081133            for (int i = 1; i < valuesCount; i += 3)
 1134            {
 451135                curves.Add(ParseCurveIndex(obj, ref currentLine, ref values));
 1136            }
 91137        }
 1138
 1139        [SuppressMessage("Globalization", "CA1303:Ne pas passer de littéraux en paramètres localisés", Justification = "
 1140        private static void ParseFreeFormType(ObjFileReaderContext context, ref ReadOnlySpan<char> value0, ref ReadOnlyS
 1141        {
 451142            if (valuesCount < 2)
 1143            {
 31144                throw new InvalidDataException("A cstype statement must specify a value.");
 1145            }
 1146
 1147            string type;
 1148
 421149            if (valuesCount == 2)
 1150            {
 181151                context.IsRationalForm = false;
 181152                type = GetNextValue(ref currentLine, ref values).ToString();
 1153            }
 241154            else if (valuesCount == 3 && GetNextValue(ref currentLine, ref values).Equals("rat", StringComparison.Ordina
 1155            {
 181156                context.IsRationalForm = true;
 181157                type = GetNextValue(ref currentLine, ref values).ToString();
 1158            }
 1159            else
 1160            {
 61161                throw new InvalidDataException("A cstype statement has too many values.");
 1162            }
 1163
 361164            switch (type.ToLowerInvariant())
 1165            {
 1166                case "bmatrix":
 61167                    context.FreeFormType = ObjFreeFormType.BasisMatrix;
 61168                    break;
 1169
 1170                case "bezier":
 61171                    context.FreeFormType = ObjFreeFormType.Bezier;
 61172                    break;
 1173
 1174                case "bspline":
 61175                    context.FreeFormType = ObjFreeFormType.BSpline;
 61176                    break;
 1177
 1178                case "cardinal":
 61179                    context.FreeFormType = ObjFreeFormType.Cardinal;
 61180                    break;
 1181
 1182                case "taylor":
 61183                    context.FreeFormType = ObjFreeFormType.Taylor;
 61184                    break;
 1185
 1186                default:
 61187                    throw new InvalidDataException("A cstype statement has an unknown type.");
 1188            }
 1189        }
 1190
 1191        [SuppressMessage("Globalization", "CA1303:Ne pas passer de littéraux en paramètres localisés", Justification = "
 1192        private static void ParseSurfaceConnection(ObjFile obj, ReadOnlySpan<char> value0, ref ReadOnlySpan<char> curren
 1193        {
 661194            if (valuesCount < 9)
 1195            {
 241196                throw new InvalidDataException("A con statement must specify 8 values.");
 1197            }
 1198
 421199            if (valuesCount != 9)
 1200            {
 31201                throw new InvalidDataException("A con statement has too many values.");
 1202            }
 1203
 391204            int surface1 = IntParse(GetNextValue(ref currentLine, ref values));
 1205
 391206            if (surface1 == 0)
 1207            {
 31208                throw new InvalidDataException("A con statement must specify a surface index.");
 1209            }
 1210
 361211            if (surface1 < 0)
 1212            {
 31213                surface1 = obj.Surfaces.Count + surface1 + 1;
 1214            }
 1215
 361216            if (surface1 <= 0 || surface1 > obj.Surfaces.Count)
 1217            {
 61218                throw new IndexOutOfRangeException();
 1219            }
 1220
 301221            var curve1 = ParseCurveIndex(obj, ref currentLine, ref values);
 1222
 211223            int surface2 = IntParse(GetNextValue(ref currentLine, ref values));
 1224
 211225            if (surface2 == 0)
 1226            {
 31227                throw new InvalidDataException("A con statement must specify a surface index.");
 1228            }
 1229
 181230            if (surface2 < 0)
 1231            {
 31232                surface2 = obj.Surfaces.Count + surface2 + 1;
 1233            }
 1234
 181235            if (surface2 <= 0 || surface2 > obj.Surfaces.Count)
 1236            {
 61237                throw new IndexOutOfRangeException();
 1238            }
 1239
 121240            var curve2 = ParseCurveIndex(obj, ref currentLine, ref values);
 1241
 31242            var connection = new ObjSurfaceConnection
 31243            {
 31244                Surface1 = surface1,
 31245                Curve2D1 = curve1,
 31246                Surface2 = surface2,
 31247                Curve2D2 = curve2
 31248            };
 1249
 31250            obj.SurfaceConnections.Add(connection);
 31251        }
 1252
 1253        private static void ParseGroupName(ObjFileReaderContext context, ReadOnlySpan<char> value0, ref ReadOnlySpan<cha
 1254        {
 871255            context.GroupNames.Clear();
 1256
 871257            if (context.Settings.OnlyOneGroupNamePerLine)
 1258            {
 61259                var sb = new StringBuilder();
 1260
 61261                sb.Append(GetNextValue(ref currentLine, ref values));
 1262
 241263                for (int i = 2; i < valuesCount; i++)
 1264                {
 61265                    sb.Append(' ');
 61266                    sb.Append(GetNextValue(ref currentLine, ref values));
 1267                }
 1268
 1269
 61270                var name = sb.ToString();
 61271                if (!string.Equals(name, "default", StringComparison.OrdinalIgnoreCase))
 1272                {
 61273                    context.GroupNames.Add(name);
 1274                }
 1275            }
 1276            else
 1277            {
 3541278                for (int i = 1; i < valuesCount; i++)
 1279                {
 961280                    var name = GetNextValue(ref currentLine, ref values).ToString();
 1281
 961282                    if (!string.Equals(name, "default", StringComparison.OrdinalIgnoreCase))
 1283                    {
 721284                        context.GroupNames.Add(name);
 1285                    }
 1286                }
 1287            }
 1288
 871289            context.GetCurrentGroups();
 871290        }
 1291
 1292        private static ObjApproximationTechnique ParseApproximationTechnique(ReadOnlySpan<char> value0, ref ReadOnlySpan
 1293        {
 1294            ObjApproximationTechnique technique;
 1295
 1201296            if (valuesCount < 2)
 1297            {
 61298                throw new InvalidDataException(string.Concat("A ", value0.ToString(), " statement must specify a techniq
 1299            }
 1300
 1141301            string value1 = GetNextValue(ref currentLine, ref values).ToString().ToLowerInvariant();
 1302
 1303            switch (value1)
 1304            {
 1305                case "cparm":
 1306                    {
 91307                        if (valuesCount < 3)
 1308                        {
 31309                            throw new InvalidDataException(string.Concat("A ", value0.ToString(), " cparm statement must
 1310                        }
 1311
 61312                        if (valuesCount != 3)
 1313                        {
 31314                            throw new InvalidDataException(string.Concat("A ", value0.ToString(), " cparm statement has 
 1315                        }
 1316
 31317                        float res = FloatParse(GetNextValue(ref currentLine, ref values));
 31318                        technique = new ObjConstantParametricSubdivisionTechnique(res);
 31319                        break;
 1320                    }
 1321
 1322                case "cparma":
 1323                    {
 121324                        if (valuesCount < 4)
 1325                        {
 61326                            throw new InvalidDataException(string.Concat("A ", value0.ToString(), " cparma statement mus
 1327                        }
 1328
 61329                        if (valuesCount != 4)
 1330                        {
 31331                            throw new InvalidDataException(string.Concat("A ", value0.ToString(), " cparma statement has
 1332                        }
 1333
 31334                        float resU = FloatParse(GetNextValue(ref currentLine, ref values));
 31335                        float resV = FloatParse(GetNextValue(ref currentLine, ref values));
 31336                        technique = new ObjConstantParametricSubdivisionTechnique(resU, resV);
 31337                        break;
 1338                    }
 1339
 1340                case "cparmb":
 1341                    {
 91342                        if (valuesCount < 3)
 1343                        {
 31344                            throw new InvalidDataException(string.Concat("A ", value0.ToString(), " cparmb statement mus
 1345                        }
 1346
 61347                        if (valuesCount != 3)
 1348                        {
 31349                            throw new InvalidDataException(string.Concat("A ", value0.ToString(), " cparmb statement has
 1350                        }
 1351
 31352                        float resU = FloatParse(GetNextValue(ref currentLine, ref values));
 31353                        technique = new ObjConstantParametricSubdivisionTechnique(resU);
 31354                        break;
 1355                    }
 1356
 1357                case "cspace":
 1358                    {
 541359                        if (valuesCount < 3)
 1360                        {
 61361                            throw new InvalidDataException(string.Concat("A ", value0.ToString(), " cspace statement mus
 1362                        }
 1363
 481364                        if (valuesCount != 3)
 1365                        {
 61366                            throw new InvalidDataException(string.Concat("A ", value0.ToString(), " cspace statement has
 1367                        }
 1368
 421369                        float length = FloatParse(GetNextValue(ref currentLine, ref values));
 421370                        technique = new ObjConstantSpatialSubdivisionTechnique(length);
 421371                        break;
 1372                    }
 1373
 1374                case "curv":
 1375                    {
 241376                        if (valuesCount < 4)
 1377                        {
 121378                            throw new InvalidDataException(string.Concat("A ", value0.ToString(), " curv statement must 
 1379                        }
 1380
 121381                        if (valuesCount != 4)
 1382                        {
 61383                            throw new InvalidDataException(string.Concat("A ", value0.ToString(), " curv statement has t
 1384                        }
 1385
 61386                        float distance = FloatParse(GetNextValue(ref currentLine, ref values));
 61387                        float angle = FloatParse(GetNextValue(ref currentLine, ref values));
 61388                        technique = new ObjCurvatureDependentSubdivisionTechnique(distance, angle);
 61389                        break;
 1390                    }
 1391
 1392                default:
 61393                    throw new InvalidDataException(string.Concat("A ", value0.ToString(), " statement contains an unknow
 1394            }
 1395
 571396            return technique;
 1397        }
 1398    }
 1399}
 1400
 1401#endif

Methods/Properties

MoveNextSkipEmpty(Polyfills.Polyfill/SpanSplitEnumerator`1<System.Char>&)
MoveNextSkipEmpty(System.MemoryExtensions/SpanSplitEnumerator`1<System.Char>&)
GetNextValue(System.ReadOnlySpan`1<System.Char>&,Polyfills.Polyfill/SpanSplitEnumerator`1<System.Char>&)
GetNextValue(System.ReadOnlySpan`1<System.Char>&,System.MemoryExtensions/SpanSplitEnumerator`1<System.Char>&)
FloatParse(System.ReadOnlySpan`1<System.Char>)
IntParse(System.ReadOnlySpan`1<System.Char>)
LongParse(System.ReadOnlySpan`1<System.Char>)
FromStream(System.IO.Stream,JeremyAnsel.Media.WavefrontObj.ObjFileReaderSettings)
ParseTriplet(JeremyAnsel.Media.WavefrontObj.ObjFile,System.ReadOnlySpan`1<System.Char>)
ParseCurveIndex(JeremyAnsel.Media.WavefrontObj.ObjFile,System.ReadOnlySpan`1<System.Char>&,Polyfills.Polyfill/SpanSplitEnumerator`1<System.Char>&)
ParseCurveIndex(JeremyAnsel.Media.WavefrontObj.ObjFile,System.ReadOnlySpan`1<System.Char>&,System.MemoryExtensions/SpanSplitEnumerator`1<System.Char>&)
ParseCurveIndex(System.Collections.Generic.List`1<JeremyAnsel.Media.WavefrontObj.ObjCurveIndex>,JeremyAnsel.Media.WavefrontObj.ObjFile,System.ReadOnlySpan`1<System.Char>,System.ReadOnlySpan`1<System.Char>&,Polyfills.Polyfill/SpanSplitEnumerator`1<System.Char>&,System.Int32)
ParseCurveIndex(System.Collections.Generic.List`1<JeremyAnsel.Media.WavefrontObj.ObjCurveIndex>,JeremyAnsel.Media.WavefrontObj.ObjFile,System.ReadOnlySpan`1<System.Char>,System.ReadOnlySpan`1<System.Char>&,System.MemoryExtensions/SpanSplitEnumerator`1<System.Char>&,System.Int32)
ParseFreeFormType(JeremyAnsel.Media.WavefrontObj.ObjFileReaderContext,System.ReadOnlySpan`1<System.Char>&,System.ReadOnlySpan`1<System.Char>&,Polyfills.Polyfill/SpanSplitEnumerator`1<System.Char>&,System.Int32)
ParseFreeFormType(JeremyAnsel.Media.WavefrontObj.ObjFileReaderContext,System.ReadOnlySpan`1<System.Char>&,System.ReadOnlySpan`1<System.Char>&,System.MemoryExtensions/SpanSplitEnumerator`1<System.Char>&,System.Int32)
ParseSurfaceConnection(JeremyAnsel.Media.WavefrontObj.ObjFile,System.ReadOnlySpan`1<System.Char>,System.ReadOnlySpan`1<System.Char>&,Polyfills.Polyfill/SpanSplitEnumerator`1<System.Char>&,System.Int32)
ParseSurfaceConnection(JeremyAnsel.Media.WavefrontObj.ObjFile,System.ReadOnlySpan`1<System.Char>,System.ReadOnlySpan`1<System.Char>&,System.MemoryExtensions/SpanSplitEnumerator`1<System.Char>&,System.Int32)
ParseGroupName(JeremyAnsel.Media.WavefrontObj.ObjFileReaderContext,System.ReadOnlySpan`1<System.Char>,System.ReadOnlySpan`1<System.Char>&,Polyfills.Polyfill/SpanSplitEnumerator`1<System.Char>&,System.Int32)
ParseGroupName(JeremyAnsel.Media.WavefrontObj.ObjFileReaderContext,System.ReadOnlySpan`1<System.Char>,System.ReadOnlySpan`1<System.Char>&,System.MemoryExtensions/SpanSplitEnumerator`1<System.Char>&,System.Int32)
ParseApproximationTechnique(System.ReadOnlySpan`1<System.Char>,System.ReadOnlySpan`1<System.Char>&,Polyfills.Polyfill/SpanSplitEnumerator`1<System.Char>&,System.Int32)
ParseApproximationTechnique(System.ReadOnlySpan`1<System.Char>,System.ReadOnlySpan`1<System.Char>&,System.MemoryExtensions/SpanSplitEnumerator`1<System.Char>&,System.Int32)