< Summary

Line coverage
99%
Covered lines: 475
Uncovered lines: 2
Coverable lines: 477
Total lines: 1182
Line coverage: 99.5%
Branch coverage
98%
Covered branches: 488
Total branches: 497
Branch coverage: 98.1%
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%
FromStream(...)97.66%300300100%
ParseMaterialColor(...)100%2222100%
ParseMaterialColor(...)100%2222100%
ParseMaterialMap(...)100%11100%
ParseMaterialMap(...)100%11100%
ParseMaterialMap(...)99.41%17117199.44%
ParseMaterialMap(...)99.41%17117199.44%

File(s)

https://raw.githubusercontent.com/JeremyAnsel/JeremyAnsel.Media.WavefrontObj/94aa747a2ae91757559f55007e09e09067df51b3/JeremyAnsel.Media.WavefrontObj/JeremyAnsel.Media.WavefrontObj/ObjMaterialFileReader9.cs

#LineLine coverage
 1// <copyright file="ObjMaterialFileReader9.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 ObjMaterialFileReader9
 23    {
 24        private static void MoveNextSkipEmpty(ref SpanSplitEnumerator values)
 25        {
 399026            while (values.MoveNext())
 27            {
 399028                if (values.Current.Start.Value != values.Current.End.Value)
 29                {
 397230                    return;
 31                }
 32            }
 033        }
 34
 35        private static ReadOnlySpan<char> GetNextValue(ref ReadOnlySpan<char> currentLine, ref SpanSplitEnumerator value
 36        {
 222037            MoveNextSkipEmpty(ref values);
 222038            return currentLine[values.Current];
 39        }
 40
 41        private static float FloatParse(ReadOnlySpan<char> s)
 42        {
 39043            return float.Parse(s, NumberStyles.Float, CultureInfo.InvariantCulture);
 44        }
 45
 46        private static int IntParse(ReadOnlySpan<char> s)
 47        {
 1248            return int.Parse(s, NumberStyles.Integer, CultureInfo.InvariantCulture);
 49        }
 50
 51        [SuppressMessage("Globalization", "CA1303:Ne pas passer de littéraux en paramètres localisés", Justification = "
 52        public static ObjMaterialFile FromStream(Stream? stream)
 53        {
 94254            if (stream == null)
 55            {
 356                throw new ArgumentNullException(nameof(stream));
 57            }
 58
 93959            var mtl = new ObjMaterialFile();
 93960            var lineReader = new LineReader9();
 61
 93962            ObjMaterial? currentMaterial = null;
 63
 93964            int valueBufferSize = 16;
 93965            Span<char> valueBuffer = stackalloc char[valueBufferSize];
 66
 495367            foreach (var currentLineString in lineReader.Read9(stream))
 68            {
 175269                ReadOnlySpan<char> currentLine = currentLineString.Buffer.AsSpan()[..currentLineString.Length];
 70
 175271                int valuesCount = 0;
 72
 1185073                foreach (Range range in currentLine.SplitAny(LineReader9.LineSeparators))
 74                {
 417375                    if (currentLine[range].Length == 0)
 76                    {
 77                        continue;
 78                    }
 79
 413780                    valuesCount++;
 81                }
 82
 175283                SpanSplitEnumerator values = currentLine.SplitAny(LineReader9.LineSeparators);
 84
 175285                MoveNextSkipEmpty(ref values);
 86
 175287                if (values.Current.End.Value - values.Current.Start.Value > valueBufferSize)
 88                {
 89                    continue;
 90                }
 91
 174992                ReadOnlySpan<char> value0 = currentLine[values.Current];
 174993                int value0Length = value0.ToLowerInvariant(valueBuffer);
 94
 95                //if (value0Length == -1)
 96                //{
 97                //    throw new InvalidDataException("the buffer is too small");
 98                //}
 99
 1749100                switch (valueBuffer[..value0Length])
 101                {
 102                    case "newmtl":
 103                        {
 834104                            if (valuesCount < 2)
 105                            {
 3106                                throw new InvalidDataException("A newmtl statement must specify a name.");
 107                            }
 108
 831109                            var sb = new StringBuilder();
 110
 831111                            sb.Append(GetNextValue(ref currentLine, ref values));
 112
 1680113                            for (int i = 2; i < valuesCount; i++)
 114                            {
 9115                                sb.Append(' ');
 9116                                sb.Append(GetNextValue(ref currentLine, ref values));
 117                            }
 118
 831119                            currentMaterial = new ObjMaterial
 831120                            {
 831121                                Name = sb.ToString()
 831122                            };
 123
 831124                            mtl.Materials.Add(currentMaterial);
 125
 831126                            break;
 127                        }
 128
 129                    case "ka":
 45130                        if (currentMaterial == null)
 131                        {
 3132                            throw new InvalidDataException("The material name is not specified.");
 133                        }
 134
 42135                        currentMaterial.AmbientColor = ParseMaterialColor("Ka", value0, ref currentLine, ref values, val
 24136                        break;
 137
 138                    case "kd":
 45139                        if (currentMaterial == null)
 140                        {
 3141                            throw new InvalidDataException("The material name is not specified.");
 142                        }
 143
 42144                        currentMaterial.DiffuseColor = ParseMaterialColor("Kd", value0, ref currentLine, ref values, val
 24145                        break;
 146
 147                    case "ke":
 45148                        if (currentMaterial == null)
 149                        {
 3150                            throw new InvalidDataException("The material name is not specified.");
 151                        }
 152
 42153                        currentMaterial.EmissiveColor = ParseMaterialColor("Ke", value0, ref currentLine, ref values, va
 24154                        break;
 155
 156                    case "ks":
 45157                        if (currentMaterial == null)
 158                        {
 3159                            throw new InvalidDataException("The material name is not specified.");
 160                        }
 161
 42162                        currentMaterial.SpecularColor = ParseMaterialColor("Ks", value0, ref currentLine, ref values, va
 24163                        break;
 164
 165                    case "tf":
 45166                        if (currentMaterial == null)
 167                        {
 3168                            throw new InvalidDataException("The material name is not specified.");
 169                        }
 170
 42171                        currentMaterial.TransmissionColor = ParseMaterialColor("Tf", value0, ref currentLine, ref values
 24172                        break;
 173
 174                    case "illum":
 12175                        if (currentMaterial == null)
 176                        {
 3177                            throw new InvalidDataException("The material name is not specified.");
 178                        }
 179
 9180                        if (valuesCount < 2)
 181                        {
 3182                            throw new InvalidDataException("An illum statement must specify an illumination model.");
 183                        }
 184
 6185                        if (valuesCount != 2)
 186                        {
 3187                            throw new InvalidDataException("An illum statement has too many values.");
 188                        }
 189
 3190                        currentMaterial.IlluminationModel = IntParse(GetNextValue(ref currentLine, ref values));
 3191                        break;
 192
 193                    case "d":
 194                        {
 21195                            if (currentMaterial == null)
 196                            {
 3197                                throw new InvalidDataException("The material name is not specified.");
 198                            }
 199
 18200                            if (valuesCount < 2)
 201                            {
 3202                                throw new InvalidDataException("A d statement must specify a factor.");
 203                            }
 204
 15205                            var value1 = GetNextValue(ref currentLine, ref values);
 206
 15207                            if (value1.Equals("-halo", StringComparison.OrdinalIgnoreCase))
 208                            {
 9209                                if (valuesCount < 3)
 210                                {
 3211                                    throw new InvalidDataException("A d statement must specify a factor.");
 212                                }
 213
 6214                                if (valuesCount != 3)
 215                                {
 3216                                    throw new InvalidDataException("A d statement has too many values.");
 217                                }
 218
 3219                                currentMaterial.IsHaloDissolve = true;
 3220                                currentMaterial.DissolveFactor = FloatParse(GetNextValue(ref currentLine, ref values));
 221                            }
 222                            else
 223                            {
 6224                                if (valuesCount != 2)
 225                                {
 3226                                    throw new InvalidDataException("A d statement has too many values.");
 227                                }
 228
 3229                                currentMaterial.DissolveFactor = FloatParse(value1);
 230                            }
 231
 3232                            break;
 233                        }
 234
 235                    case "ns":
 12236                        if (currentMaterial == null)
 237                        {
 3238                            throw new InvalidDataException("The material name is not specified.");
 239                        }
 240
 9241                        if (valuesCount < 2)
 242                        {
 3243                            throw new InvalidDataException("A Ns statement must specify a specular exponent.");
 244                        }
 245
 6246                        if (valuesCount != 2)
 247                        {
 3248                            throw new InvalidDataException("A Ns statement has too many values.");
 249                        }
 250
 3251                        currentMaterial.SpecularExponent = FloatParse(GetNextValue(ref currentLine, ref values));
 3252                        break;
 253
 254                    case "sharpness":
 12255                        if (currentMaterial == null)
 256                        {
 3257                            throw new InvalidDataException("The material name is not specified.");
 258                        }
 259
 9260                        if (valuesCount < 2)
 261                        {
 3262                            throw new InvalidDataException("A sharpness statement must specify a sharpness value.");
 263                        }
 264
 6265                        if (valuesCount != 2)
 266                        {
 3267                            throw new InvalidDataException("A sharpness statement has too many values.");
 268                        }
 269
 3270                        currentMaterial.Sharpness = IntParse(GetNextValue(ref currentLine, ref values));
 3271                        break;
 272
 273                    case "ni":
 12274                        if (currentMaterial == null)
 275                        {
 3276                            throw new InvalidDataException("The material name is not specified.");
 277                        }
 278
 9279                        if (valuesCount < 2)
 280                        {
 3281                            throw new InvalidDataException("A Ni statement must specify an optical density.");
 282                        }
 283
 6284                        if (valuesCount != 2)
 285                        {
 3286                            throw new InvalidDataException("A Ni statement has too many values.");
 287                        }
 288
 3289                        currentMaterial.OpticalDensity = FloatParse(GetNextValue(ref currentLine, ref values));
 3290                        break;
 291
 292                    case "map_aat":
 293                        {
 18294                            if (currentMaterial == null)
 295                            {
 3296                                throw new InvalidDataException("The material name is not specified.");
 297                            }
 298
 15299                            if (valuesCount < 2)
 300                            {
 3301                                throw new InvalidDataException("A map_aat statement must specify a value.");
 302                            }
 303
 12304                            if (valuesCount != 2)
 305                            {
 3306                                throw new InvalidDataException("A map_aat statement has too many values.");
 307                            }
 308
 9309                            var value1 = GetNextValue(ref currentLine, ref values);
 310
 9311                            if (value1.Equals("on", StringComparison.OrdinalIgnoreCase))
 312                            {
 3313                                currentMaterial.IsAntiAliasingEnabled = true;
 314                            }
 6315                            else if (value1.Equals("off", StringComparison.OrdinalIgnoreCase))
 316                            {
 3317                                currentMaterial.IsAntiAliasingEnabled = false;
 318                            }
 319                            else
 320                            {
 3321                                throw new InvalidDataException("A map_aat statement must specify on or off.");
 322                            }
 323
 324                            break;
 325                        }
 326
 327                    case "map_ka":
 201328                        if (currentMaterial == null)
 329                        {
 3330                            throw new InvalidDataException("The material name is not specified.");
 331                        }
 332
 198333                        currentMaterial.AmbientMap = ParseMaterialMap("map_Ka", value0, ref currentLine, ref values, val
 96334                        break;
 335
 336                    case "map_kd":
 21337                        if (currentMaterial == null)
 338                        {
 3339                            throw new InvalidDataException("The material name is not specified.");
 340                        }
 341
 18342                        currentMaterial.DiffuseMap = ParseMaterialMap("map_Kd", value0, ref currentLine, ref values, val
 15343                        break;
 344
 345                    case "map_ke":
 21346                        if (currentMaterial == null)
 347                        {
 3348                            throw new InvalidDataException("The material name is not specified.");
 349                        }
 350
 18351                        currentMaterial.EmissiveMap = ParseMaterialMap("map_Ke", value0, ref currentLine, ref values, va
 15352                        break;
 353
 354                    case "map_ks":
 21355                        if (currentMaterial == null)
 356                        {
 3357                            throw new InvalidDataException("The material name is not specified.");
 358                        }
 359
 18360                        currentMaterial.SpecularMap = ParseMaterialMap("map_Ks", value0, ref currentLine, ref values, va
 15361                        break;
 362
 363                    case "map_ns":
 21364                        if (currentMaterial == null)
 365                        {
 3366                            throw new InvalidDataException("The material name is not specified.");
 367                        }
 368
 18369                        currentMaterial.SpecularExponentMap = ParseMaterialMap("map_Ns", value0, ref currentLine, ref va
 15370                        break;
 371
 372                    case "map_d":
 373                    case "map_tr":
 21374                        if (currentMaterial == null)
 375                        {
 3376                            throw new InvalidDataException("The material name is not specified.");
 377                        }
 378
 18379                        currentMaterial.DissolveMap = ParseMaterialMap("map_d", value0, ref currentLine, ref values, val
 15380                        break;
 381
 382                    case "decal":
 383                    case "map_decal":
 15384                        if (currentMaterial == null)
 385                        {
 3386                            throw new InvalidDataException("The material name is not specified.");
 387                        }
 388
 12389                        currentMaterial.DecalMap = ParseMaterialMap("decal", value0, ref currentLine, ref values, values
 9390                        break;
 391
 392                    case "disp":
 393                    case "map_disp":
 15394                        if (currentMaterial == null)
 395                        {
 3396                            throw new InvalidDataException("The material name is not specified.");
 397                        }
 398
 12399                        currentMaterial.DispMap = ParseMaterialMap("disp", value0, ref currentLine, ref values, valuesCo
 9400                        break;
 401
 402                    case "bump":
 403                    case "map_bump":
 9404                        if (currentMaterial == null)
 405                        {
 3406                            throw new InvalidDataException("The material name is not specified.");
 407                        }
 408
 6409                        currentMaterial.BumpMap = ParseMaterialMap("bump", value0, ref currentLine, ref values, valuesCo
 3410                        break;
 411
 412                    case "refl":
 413                    case "map_refl":
 84414                        if (currentMaterial == null)
 415                        {
 3416                            throw new InvalidDataException("The material name is not specified.");
 417                        }
 418
 81419                        if (valuesCount < 4)
 420                        {
 12421                            throw new InvalidDataException("A refl statement must specify a type and a file name.");
 422                        }
 423
 69424                        ObjMaterialMap materialMap = ParseMaterialMap("refl", value0, ref currentLine, ref values, value
 425
 426                        switch (materialMapType)
 427                        {
 428                            case MaterialMapType.Sphere:
 9429                                currentMaterial.ReflectionMap.Sphere = materialMap;
 9430                                break;
 431
 432                            case MaterialMapType.CubeTop:
 9433                                currentMaterial.ReflectionMap.CubeTop = materialMap;
 9434                                break;
 435
 436                            case MaterialMapType.CubeBottom:
 9437                                currentMaterial.ReflectionMap.CubeBottom = materialMap;
 9438                                break;
 439
 440                            case MaterialMapType.CubeFront:
 9441                                currentMaterial.ReflectionMap.CubeFront = materialMap;
 9442                                break;
 443
 444                            case MaterialMapType.CubeBack:
 9445                                currentMaterial.ReflectionMap.CubeBack = materialMap;
 9446                                break;
 447
 448                            case MaterialMapType.CubeLeft:
 9449                                currentMaterial.ReflectionMap.CubeLeft = materialMap;
 9450                                break;
 451
 452                            case MaterialMapType.CubeRight:
 9453                                currentMaterial.ReflectionMap.CubeRight = materialMap;
 9454                                break;
 455                        }
 456
 457                        break;
 458                    case "pr":
 12459                        if (currentMaterial == null)
 460                        {
 3461                            throw new InvalidDataException("The material name is not specified.");
 462                        }
 463
 9464                        if (valuesCount < 2)
 465                        {
 3466                            throw new InvalidDataException("A Pr statement must specify an optical density.");
 467                        }
 468
 6469                        if (valuesCount != 2)
 470                        {
 3471                            throw new InvalidDataException("A Pr statement has too many values.");
 472                        }
 473
 3474                        currentMaterial.Roughness = FloatParse(GetNextValue(ref currentLine, ref values));
 3475                        break;
 476                    case "map_pr":
 21477                        if (currentMaterial == null)
 478                        {
 3479                            throw new InvalidDataException("The material name is not specified.");
 480                        }
 481
 18482                        currentMaterial.RoughnessMap = ParseMaterialMap("map_Pr", value0, ref currentLine, ref values, v
 15483                        break;
 484                    case "pm":
 12485                        if (currentMaterial == null)
 486                        {
 3487                            throw new InvalidDataException("The material name is not specified.");
 488                        }
 489
 9490                        if (valuesCount < 2)
 491                        {
 3492                            throw new InvalidDataException("A Pm statement must specify an optical density.");
 493                        }
 494
 6495                        if (valuesCount != 2)
 496                        {
 3497                            throw new InvalidDataException("A Pm statement has too many values.");
 498                        }
 499
 3500                        currentMaterial.Metallic = FloatParse(GetNextValue(ref currentLine, ref values));
 3501                        break;
 502                    case "map_pm":
 21503                        if (currentMaterial == null)
 504                        {
 3505                            throw new InvalidDataException("The material name is not specified.");
 506                        }
 507
 18508                        currentMaterial.MetallicMap = ParseMaterialMap("map_Pm", value0, ref currentLine, ref values, va
 15509                        break;
 510                    case "ps":
 12511                        if (currentMaterial == null)
 512                        {
 3513                            throw new InvalidDataException("The material name is not specified.");
 514                        }
 515
 9516                        if (valuesCount < 2)
 517                        {
 3518                            throw new InvalidDataException("A Ps statement must specify an optical density.");
 519                        }
 520
 6521                        if (valuesCount != 2)
 522                        {
 3523                            throw new InvalidDataException("A Ps statement has too many values.");
 524                        }
 525
 3526                        currentMaterial.Sheen = FloatParse(GetNextValue(ref currentLine, ref values));
 3527                        break;
 528                    case "map_ps":
 21529                        if (currentMaterial == null)
 530                        {
 3531                            throw new InvalidDataException("The material name is not specified.");
 532                        }
 533
 18534                        currentMaterial.SheenMap = ParseMaterialMap("map_Ps", value0, ref currentLine, ref values, value
 15535                        break;
 536                    case "pc":
 12537                        if (currentMaterial == null)
 538                        {
 3539                            throw new InvalidDataException("The material name is not specified.");
 540                        }
 541
 9542                        if (valuesCount < 2)
 543                        {
 3544                            throw new InvalidDataException("A Pc statement must specify an optical density.");
 545                        }
 546
 6547                        if (valuesCount != 2)
 548                        {
 3549                            throw new InvalidDataException("A Pc statement has too many values.");
 550                        }
 551
 3552                        currentMaterial.ClearCoatThickness = FloatParse(GetNextValue(ref currentLine, ref values));
 3553                        break;
 554                    case "pcr":
 12555                        if (currentMaterial == null)
 556                        {
 3557                            throw new InvalidDataException("The material name is not specified.");
 558                        }
 559
 9560                        if (valuesCount < 2)
 561                        {
 3562                            throw new InvalidDataException("A Pcr statement must specify an optical density.");
 563                        }
 564
 6565                        if (valuesCount != 2)
 566                        {
 3567                            throw new InvalidDataException("A Pcr statement has too many values.");
 568                        }
 569
 3570                        currentMaterial.ClearCoatRoughness = FloatParse(GetNextValue(ref currentLine, ref values));
 3571                        break;
 572                    case "aniso":
 12573                        if (currentMaterial == null)
 574                        {
 3575                            throw new InvalidDataException("The material name is not specified.");
 576                        }
 577
 9578                        if (valuesCount < 2)
 579                        {
 3580                            throw new InvalidDataException("A aniso statement must specify an optical density.");
 581                        }
 582
 6583                        if (valuesCount != 2)
 584                        {
 3585                            throw new InvalidDataException("A aniso statement has too many values.");
 586                        }
 587
 3588                        currentMaterial.Anisotropy = FloatParse(GetNextValue(ref currentLine, ref values));
 3589                        break;
 590                    case "anisor":
 12591                        if (currentMaterial == null)
 592                        {
 3593                            throw new InvalidDataException("The material name is not specified.");
 594                        }
 595
 9596                        if (valuesCount < 2)
 597                        {
 3598                            throw new InvalidDataException("A anisor statement must specify an optical density.");
 599                        }
 600
 6601                        if (valuesCount != 2)
 602                        {
 3603                            throw new InvalidDataException("A anisor statement has too many values.");
 604                        }
 605
 3606                        currentMaterial.AnisotropyRotation = FloatParse(GetNextValue(ref currentLine, ref values));
 3607                        break;
 608                    case "norm":
 21609                        if (currentMaterial == null)
 610                        {
 3611                            throw new InvalidDataException("The material name is not specified.");
 612                        }
 613
 18614                        currentMaterial.Norm = ParseMaterialMap("norm", value0, ref currentLine, ref values, valuesCount
 615                        break;
 616                }
 617            }
 618
 510619            mtl.HeaderText = string.Join("\n", lineReader.HeaderTextLines.ToArray());
 620
 510621            return mtl;
 622        }
 623
 624        [SuppressMessage("Globalization", "CA1303:Ne pas passer de littéraux en paramètres localisés", Justification = "
 625        private static ObjMaterialColor ParseMaterialColor(ReadOnlySpan<char> statement, ReadOnlySpan<char> value0, ref 
 626        {
 210627            if (valuesCount < 2)
 628            {
 15629                throw new InvalidDataException(string.Concat("A ", statement, " statement must specify a color."));
 630            }
 631
 195632            var color = new ObjMaterialColor();
 633
 195634            ReadOnlySpan<char> value1 = GetNextValue(ref currentLine, ref values);
 195635            Span<char> valueBuffer = stackalloc char[value1.Length];
 195636            int value1Length = value1.ToLowerInvariant(valueBuffer);
 637
 638            //if (value1Length == -1)
 639            //{
 640            //    throw new InvalidDataException("the buffer is too small");
 641            //}
 642
 195643            int index = 1;
 644
 195645            switch (valueBuffer[..value1Length])
 646            {
 647                case "spectral":
 60648                    index++;
 649
 60650                    if (valuesCount - index < 1)
 651                    {
 15652                        throw new InvalidDataException(string.Concat("A ", statement, " spectral statement must specify 
 653                    }
 654
 45655                    color.SpectralFileName = GetNextValue(ref currentLine, ref values).ToString();
 45656                    index++;
 657
 45658                    if (valuesCount > index)
 659                    {
 30660                        color.SpectralFactor = FloatParse(GetNextValue(ref currentLine, ref values));
 30661                        index++;
 662                    }
 663
 30664                    break;
 665
 666                case "xyz":
 60667                    index++;
 668
 60669                    if (valuesCount - index < 1)
 670                    {
 15671                        throw new InvalidDataException(string.Concat("A ", statement, " xyz statement must specify a col
 672                    }
 673
 45674                    color.UseXYZColorSpace = true;
 675
 45676                    var xyz = new ObjVector3();
 677
 45678                    xyz.X = FloatParse(GetNextValue(ref currentLine, ref values));
 45679                    index++;
 680
 45681                    if (valuesCount > index)
 682                    {
 30683                        if (valuesCount - index < 2)
 684                        {
 15685                            throw new InvalidDataException(string.Concat("A ", statement, " xyz statement must specify a
 686                        }
 687
 15688                        xyz.Y = FloatParse(GetNextValue(ref currentLine, ref values));
 15689                        xyz.Z = FloatParse(GetNextValue(ref currentLine, ref values));
 15690                        index += 2;
 691                    }
 692                    else
 693                    {
 15694                        xyz.Y = xyz.X;
 15695                        xyz.Z = xyz.X;
 696                    }
 697
 30698                    color.Color = xyz;
 30699                    break;
 700
 701                default:
 75702                    var rgb = new ObjVector3();
 703
 75704                    rgb.X = FloatParse(value1);
 75705                    index++;
 706
 75707                    if (valuesCount > index)
 708                    {
 60709                        if (valuesCount - index < 2)
 710                        {
 15711                            throw new InvalidDataException(string.Concat("A ", statement, " statement must specify a RGB
 712                        }
 713
 45714                        rgb.Y = FloatParse(GetNextValue(ref currentLine, ref values));
 45715                        rgb.Z = FloatParse(GetNextValue(ref currentLine, ref values));
 45716                        index += 2;
 717                    }
 718                    else
 719                    {
 15720                        rgb.Y = rgb.X;
 15721                        rgb.Z = rgb.X;
 722                    }
 723
 60724                    color.Color = rgb;
 725                    break;
 726            }
 727
 135728            if (index != valuesCount)
 729            {
 15730                throw new InvalidDataException(string.Concat("A ", statement, " statement has too many values."));
 731            }
 732
 120733            return color;
 734        }
 735
 736        private enum MaterialMapType
 737        {
 738            None,
 739            Sphere,
 740            CubeTop,
 741            CubeBottom,
 742            CubeFront,
 743            CubeBack,
 744            CubeLeft,
 745            CubeRight
 746        }
 747
 748        [SuppressMessage("Globalization", "CA1303:Ne pas passer de littéraux en paramètres localisés", Justification = "
 749        private static ObjMaterialMap ParseMaterialMap(ReadOnlySpan<char> statement, ReadOnlySpan<char> value0, ref Read
 750        {
 390751            return ParseMaterialMap(statement, value0, ref currentLine, ref values, valuesCount, out _);
 752        }
 753
 754        [SuppressMessage("Globalization", "CA1303:Ne pas passer de littéraux en paramètres localisés", Justification = "
 755        private static ObjMaterialMap ParseMaterialMap(ReadOnlySpan<char> statement, ReadOnlySpan<char> value0, ref Read
 756        {
 459757            materialMapType = MaterialMapType.None;
 758
 459759            var map = new ObjMaterialMap();
 760
 459761            int valueBufferSize = 16;
 459762            Span<char> valueBuffer = stackalloc char[valueBufferSize];
 763
 1347764            for (int index = 0; index < valuesCount;)
 765            {
 630766                index++;
 767
 630768                if (valuesCount - index < 1)
 769                {
 66770                    throw new InvalidDataException(string.Concat("A ", statement, " statement must specify a filename.")
 771                }
 772
 564773                ReadOnlySpan<char> value1 = GetNextValue(ref currentLine, ref values);
 564774                int value1Length = value1.ToLowerInvariant(valueBuffer);
 775
 776                // Value1Length is -1 when the buffer is too small.
 777                // This should only happen if the value is a file name and not an option
 564778                if (value1Length == -1)
 779                {
 60780                    if (index == 1)
 781                    {
 60782                        if (statement.Equals("refl", StringComparison.OrdinalIgnoreCase))
 783                        {
 0784                            throw new InvalidDataException("A refl statement must specify a type.");
 785                        }
 786                    }
 787
 60788                    var sb = new StringBuilder();
 789
 60790                    sb.Append(value1);
 791
 180792                    for (int i = index + 1; i < valuesCount; i++)
 793                    {
 30794                        sb.Append(' ');
 30795                        sb.Append(GetNextValue(ref currentLine, ref values));
 796                    }
 797
 60798                    string filename = sb.ToString();
 799
 60800                    map.FileName = filename;
 60801                    return map;
 802                }
 803
 504804                if (statement.Equals("refl", StringComparison.OrdinalIgnoreCase))
 805                {
 135806                    if (index == 1)
 807                    {
 69808                        if (!MemoryExtensions.Equals(valueBuffer[..value1Length], "-type", StringComparison.OrdinalIgnor
 809                        {
 3810                            throw new InvalidDataException("A refl statement must specify a type.");
 811                        }
 812                    }
 813                }
 814
 501815                switch (valueBuffer[..value1Length])
 816                {
 817                    case "-type":
 72818                        if (valuesCount - index < 2)
 819                        {
 3820                            throw new InvalidDataException(string.Concat("A ", statement, " -type option must specify a 
 821                        }
 822
 69823                        if (statement.Equals("refl", StringComparison.OrdinalIgnoreCase))
 824                        {
 66825                            ReadOnlySpan<char> value2 = GetNextValue(ref currentLine, ref values);
 66826                            int value2Length = value2.ToLowerInvariant(valueBuffer);
 827
 828                            //if (value2Length == -1)
 829                            //{
 830                            //    throw new InvalidDataException("the buffer is too small");
 831                            //}
 832
 66833                            switch (valueBuffer[..value2Length])
 834                            {
 835                                case "sphere":
 9836                                    materialMapType = MaterialMapType.Sphere;
 9837                                    break;
 838
 839                                case "cube_top":
 9840                                    materialMapType = MaterialMapType.CubeTop;
 9841                                    break;
 842
 843                                case "cube_bottom":
 9844                                    materialMapType = MaterialMapType.CubeBottom;
 9845                                    break;
 846
 847                                case "cube_front":
 9848                                    materialMapType = MaterialMapType.CubeFront;
 9849                                    break;
 850
 851                                case "cube_back":
 9852                                    materialMapType = MaterialMapType.CubeBack;
 9853                                    break;
 854
 855                                case "cube_left":
 9856                                    materialMapType = MaterialMapType.CubeLeft;
 9857                                    break;
 858
 859                                case "cube_right":
 9860                                    materialMapType = MaterialMapType.CubeRight;
 9861                                    break;
 862                            }
 863                        }
 864                        else
 865                        {
 3866                            GetNextValue(ref currentLine, ref values);
 867                        }
 868
 69869                        index++;
 69870                        break;
 871
 872                    case "-blenu":
 873                        {
 15874                            if (valuesCount - index < 2)
 875                            {
 3876                                throw new InvalidDataException(string.Concat("A ", statement, " -blenu option must speci
 877                            }
 878
 12879                            var value2 = GetNextValue(ref currentLine, ref values);
 880
 12881                            if (value2.Equals("on", StringComparison.OrdinalIgnoreCase))
 882                            {
 3883                                map.IsHorizontalBlendingEnabled = true;
 884                            }
 9885                            else if (value2.Equals("off", StringComparison.OrdinalIgnoreCase))
 886                            {
 3887                                map.IsHorizontalBlendingEnabled = false;
 888                            }
 889                            else
 890                            {
 6891                                throw new InvalidDataException(string.Concat("A ", statement, " -blenu option must speci
 892                            }
 893
 6894                            index++;
 6895                            break;
 896                        }
 897
 898                    case "-blenv":
 899                        {
 15900                            if (valuesCount - index < 2)
 901                            {
 3902                                throw new InvalidDataException(string.Concat("A ", statement, " -blenv option must speci
 903                            }
 904
 12905                            var value2 = GetNextValue(ref currentLine, ref values);
 906
 12907                            if (value2.Equals("on", StringComparison.OrdinalIgnoreCase))
 908                            {
 3909                                map.IsVerticalBlendingEnabled = true;
 910                            }
 9911                            else if (value2.Equals("off", StringComparison.OrdinalIgnoreCase))
 912                            {
 3913                                map.IsVerticalBlendingEnabled = false;
 914                            }
 915                            else
 916                            {
 6917                                throw new InvalidDataException(string.Concat("A ", statement, " -blenv option must speci
 918                            }
 919
 6920                            index++;
 6921                            break;
 922                        }
 923
 924                    case "-bm":
 9925                        if (valuesCount - index < 2)
 926                        {
 3927                            throw new InvalidDataException(string.Concat("A ", statement, " -bm option must specify a va
 928                        }
 929
 6930                        map.BumpMultiplier = FloatParse(GetNextValue(ref currentLine, ref values));
 931
 6932                        index++;
 6933                        break;
 934
 935                    case "-boost":
 9936                        if (valuesCount - index < 2)
 937                        {
 3938                            throw new InvalidDataException(string.Concat("A ", statement, " -boost option must specify a
 939                        }
 940
 6941                        map.Boost = FloatParse(GetNextValue(ref currentLine, ref values));
 942
 6943                        index++;
 6944                        break;
 945
 946                    case "-cc":
 947                        {
 15948                            if (valuesCount - index < 2)
 949                            {
 3950                                throw new InvalidDataException(string.Concat("A ", statement, " -cc option must specify 
 951                            }
 952
 12953                            var value2 = GetNextValue(ref currentLine, ref values);
 954
 12955                            if (value2.Equals("on", StringComparison.OrdinalIgnoreCase))
 956                            {
 3957                                map.IsColorCorrectionEnabled = true;
 958                            }
 9959                            else if (value2.Equals("off", StringComparison.OrdinalIgnoreCase))
 960                            {
 3961                                map.IsColorCorrectionEnabled = false;
 962                            }
 963                            else
 964                            {
 6965                                throw new InvalidDataException(string.Concat("A ", statement, " -cc option must specify 
 966                            }
 967
 6968                            index++;
 6969                            break;
 970                        }
 971
 972                    case "-clamp":
 973                        {
 15974                            if (valuesCount - index < 2)
 975                            {
 3976                                throw new InvalidDataException(string.Concat("A ", statement, " -clamp option must speci
 977                            }
 978
 12979                            var value2 = GetNextValue(ref currentLine, ref values);
 980
 12981                            if (value2.Equals("on", StringComparison.OrdinalIgnoreCase))
 982                            {
 3983                                map.IsClampingEnabled = true;
 984                            }
 9985                            else if (value2.Equals("off", StringComparison.OrdinalIgnoreCase))
 986                            {
 3987                                map.IsClampingEnabled = false;
 988                            }
 989                            else
 990                            {
 6991                                throw new InvalidDataException(string.Concat("A ", statement, " -clamp option must speci
 992                            }
 993
 6994                            index++;
 6995                            break;
 996                        }
 997
 998                    case "-imfchan":
 999                        {
 271000                            if (valuesCount - index < 2)
 1001                            {
 31002                                throw new InvalidDataException(string.Concat("A ", statement, " -imfchan option must spe
 1003                            }
 1004
 241005                            ReadOnlySpan<char> value2 = GetNextValue(ref currentLine, ref values);
 241006                            int value2Length = value2.ToLowerInvariant(valueBuffer);
 1007
 1008                            //if (value2Length == -1)
 1009                            //{
 1010                            //    throw new InvalidDataException("the buffer is too small");
 1011                            //}
 1012
 241013                            switch (valueBuffer[..value2Length])
 1014                            {
 1015                                case "r":
 31016                                    map.ScalarChannel = ObjMapChannel.Red;
 31017                                    break;
 1018
 1019                                case "g":
 31020                                    map.ScalarChannel = ObjMapChannel.Green;
 31021                                    break;
 1022
 1023                                case "b":
 31024                                    map.ScalarChannel = ObjMapChannel.Blue;
 31025                                    break;
 1026
 1027                                case "m":
 31028                                    map.ScalarChannel = ObjMapChannel.Matte;
 31029                                    break;
 1030
 1031                                case "l":
 31032                                    map.ScalarChannel = ObjMapChannel.Luminance;
 31033                                    break;
 1034
 1035                                case "z":
 31036                                    map.ScalarChannel = ObjMapChannel.Depth;
 31037                                    break;
 1038
 1039                                default:
 61040                                    throw new InvalidDataException(string.Concat("A ", statement, " -imfchan option must
 1041                            }
 1042
 181043                            index++;
 181044                            break;
 1045                        }
 1046
 1047                    case "-mm":
 121048                        if (valuesCount - index < 3)
 1049                        {
 61050                            throw new InvalidDataException(string.Concat("A ", statement, " -mm option must specify a ba
 1051                        }
 1052
 61053                        map.ModifierBase = FloatParse(GetNextValue(ref currentLine, ref values));
 61054                        map.ModifierGain = FloatParse(GetNextValue(ref currentLine, ref values));
 1055
 61056                        index += 2;
 61057                        break;
 1058
 1059                    case "-o":
 151060                        if (valuesCount - index < 2)
 1061                        {
 31062                            throw new InvalidDataException(string.Concat("A ", statement, " -o option must specify at le
 1063                        }
 1064
 121065                        var offset = new ObjVector3();
 1066
 121067                        offset.X = FloatParse(GetNextValue(ref currentLine, ref values));
 1068
 121069                        if (valuesCount - index > 3)
 1070                        {
 61071                            offset.Y = FloatParse(GetNextValue(ref currentLine, ref values));
 1072
 61073                            if (valuesCount - index > 4)
 1074                            {
 31075                                offset.Z = FloatParse(GetNextValue(ref currentLine, ref values));
 31076                                index++;
 1077                            }
 1078
 61079                            index++;
 1080                        }
 1081
 121082                        index++;
 1083
 121084                        map.Offset = offset;
 121085                        break;
 1086
 1087                    case "-s":
 151088                        if (valuesCount - index < 2)
 1089                        {
 31090                            throw new InvalidDataException(string.Concat("A ", statement, " -s option must specify at le
 1091                        }
 1092
 121093                        var scale = new ObjVector3(1.0f, 1.0f, 1.0f);
 1094
 121095                        scale.X = FloatParse(GetNextValue(ref currentLine, ref values));
 1096
 121097                        if (valuesCount - index > 3)
 1098                        {
 61099                            scale.Y = FloatParse(GetNextValue(ref currentLine, ref values));
 1100
 61101                            if (valuesCount - index > 4)
 1102                            {
 31103                                scale.Z = FloatParse(GetNextValue(ref currentLine, ref values));
 31104                                index++;
 1105                            }
 1106
 61107                            index++;
 1108                        }
 1109
 121110                        index++;
 1111
 121112                        map.Scale = scale;
 121113                        break;
 1114
 1115                    case "-t":
 151116                        if (valuesCount - index < 2)
 1117                        {
 31118                            throw new InvalidDataException(string.Concat("A ", statement, " -t option must specify at le
 1119                        }
 1120
 121121                        var turbulence = new ObjVector3();
 1122
 121123                        turbulence.X = FloatParse(GetNextValue(ref currentLine, ref values));
 1124
 121125                        if (valuesCount - index > 3)
 1126                        {
 61127                            turbulence.Y = FloatParse(GetNextValue(ref currentLine, ref values));
 1128
 61129                            if (valuesCount - index > 4)
 1130                            {
 31131                                turbulence.Z = FloatParse(GetNextValue(ref currentLine, ref values));
 31132                                index++;
 1133                            }
 1134
 61135                            index++;
 1136                        }
 1137
 121138                        index++;
 1139
 121140                        map.Turbulence = turbulence;
 121141                        break;
 1142
 1143                    case "-texres":
 91144                        if (valuesCount - index < 2)
 1145                        {
 31146                            throw new InvalidDataException(string.Concat("A ", statement, " -texres option must specify 
 1147                        }
 1148
 61149                        map.TextureResolution = IntParse(GetNextValue(ref currentLine, ref values));
 1150
 61151                        index++;
 61152                        break;
 1153
 1154                    default:
 1155                        {
 2581156                            var sb = new StringBuilder();
 1157
 2581158                            sb.Append(value1);
 1159
 6301160                            for (int i = index + 1; i < valuesCount; i++)
 1161                            {
 571162                                sb.Append(' ');
 571163                                sb.Append(GetNextValue(ref currentLine, ref values));
 1164                            }
 1165
 2581166                            string filename = sb.ToString();
 1167
 2581168                            map.FileName = filename;
 2581169                            index = valuesCount;
 1170
 1171                            break;
 1172                        }
 1173                }
 1174            }
 1175
 2581176            return map;
 1177        }
 1178    }
 1179}
 1180
 1181#endif
 1182

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>)
FromStream(System.IO.Stream)
ParseMaterialColor(System.ReadOnlySpan`1<System.Char>,System.ReadOnlySpan`1<System.Char>,System.ReadOnlySpan`1<System.Char>&,Polyfills.Polyfill/SpanSplitEnumerator`1<System.Char>&,System.Int32)
ParseMaterialColor(System.ReadOnlySpan`1<System.Char>,System.ReadOnlySpan`1<System.Char>,System.ReadOnlySpan`1<System.Char>&,System.MemoryExtensions/SpanSplitEnumerator`1<System.Char>&,System.Int32)
ParseMaterialMap(System.ReadOnlySpan`1<System.Char>,System.ReadOnlySpan`1<System.Char>,System.ReadOnlySpan`1<System.Char>&,Polyfills.Polyfill/SpanSplitEnumerator`1<System.Char>&,System.Int32)
ParseMaterialMap(System.ReadOnlySpan`1<System.Char>,System.ReadOnlySpan`1<System.Char>,System.ReadOnlySpan`1<System.Char>&,System.MemoryExtensions/SpanSplitEnumerator`1<System.Char>&,System.Int32)
ParseMaterialMap(System.ReadOnlySpan`1<System.Char>,System.ReadOnlySpan`1<System.Char>,System.ReadOnlySpan`1<System.Char>&,Polyfills.Polyfill/SpanSplitEnumerator`1<System.Char>&,System.Int32,JeremyAnsel.Media.WavefrontObj.ObjMaterialFileReader9/MaterialMapType&)
ParseMaterialMap(System.ReadOnlySpan`1<System.Char>,System.ReadOnlySpan`1<System.Char>,System.ReadOnlySpan`1<System.Char>&,System.MemoryExtensions/SpanSplitEnumerator`1<System.Char>&,System.Int32,JeremyAnsel.Media.WavefrontObj.ObjMaterialFileReader9/MaterialMapType&)