< Summary

Line coverage
99%
Covered lines: 476
Uncovered lines: 2
Coverable lines: 478
Total lines: 1184
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/636b700b450d7d3262bf9218a7cc67966be4ced8/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        {
 396626            while (values.MoveNext())
 27            {
 396628                if (values.Current.Start.Value != values.Current.End.Value)
 29                {
 394830                    return;
 31                }
 32            }
 033        }
 34
 35        private static ReadOnlySpan<char> GetNextValue(ref ReadOnlySpan<char> currentLine, ref SpanSplitEnumerator value
 36        {
 219937            MoveNextSkipEmpty(ref values);
 219938            return currentLine[values.Current];
 39        }
 40
 41        private static float FloatParse(ReadOnlySpan<char> s)
 42        {
 34543            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        {
 93954            if (stream == null)
 55            {
 356                throw new ArgumentNullException(nameof(stream));
 57            }
 58
 93659            var mtl = new ObjMaterialFile();
 93660            var lineReader = new LineReader9();
 61
 93662            ObjMaterial? currentMaterial = null;
 63
 93664            int valueBufferSize = 16;
 93665            Span<char> valueBuffer = stackalloc char[valueBufferSize];
 66
 494167            foreach (var currentLineString in lineReader.Read9(stream))
 68            {
 174969                ReadOnlySpan<char> currentLine = currentLineString.Buffer.AsSpan()[..currentLineString.Length];
 70
 174971                int valuesCount = 0;
 72
 1179673                foreach (Range range in currentLine.SplitAny(LineReader9.LineSeparators))
 74                {
 414975                    if (currentLine[range].Length == 0)
 76                    {
 77                        continue;
 78                    }
 79
 411380                    valuesCount++;
 81                }
 82
 174983                SpanSplitEnumerator values = currentLine.SplitAny(LineReader9.LineSeparators);
 84
 174985                MoveNextSkipEmpty(ref values);
 86
 174987                if (values.Current.End.Value - values.Current.Start.Value > valueBufferSize)
 88                {
 89                    continue;
 90                }
 91
 174692                ReadOnlySpan<char> value0 = currentLine[values.Current];
 174693                int value0Length = value0.ToLowerInvariant(valueBuffer);
 94
 95                //if (value0Length == -1)
 96                //{
 97                //    throw new InvalidDataException("the buffer is too small");
 98                //}
 99
 1746100                switch (valueBuffer[..value0Length])
 101                {
 102                    case "newmtl":
 103                        {
 831104                            if (valuesCount < 2)
 105                            {
 3106                                throw new InvalidDataException("A newmtl statement must specify a name.");
 107                            }
 108
 828109                            var sb = new StringBuilder();
 110
 828111                            sb.Append(GetNextValue(ref currentLine, ref values));
 112
 1668113                            for (int i = 2; i < valuesCount; i++)
 114                            {
 6115                                sb.Append(' ');
 6116                                sb.Append(GetNextValue(ref currentLine, ref values));
 117                            }
 118
 828119                            currentMaterial = new ObjMaterial
 828120                            {
 828121                                Name = sb.ToString()
 828122                            };
 123
 828124                            mtl.Materials.Add(currentMaterial);
 125
 828126                            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
 507619            mtl.HeaderText = string.Join("\n", lineReader.HeaderTextLines.ToArray());
 620
 507621            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            int valueBufferSize = 16;
 195635            Span<char> valueBuffer = stackalloc char[valueBufferSize];
 636
 195637            ReadOnlySpan<char> value1 = GetNextValue(ref currentLine, ref values);
 195638            int value1Length = value1.ToLowerInvariant(valueBuffer);
 639
 640            //if (value1Length == -1)
 641            //{
 642            //    throw new InvalidDataException("the buffer is too small");
 643            //}
 644
 195645            int index = 1;
 646
 195647            switch (valueBuffer[..value1Length])
 648            {
 649                case "spectral":
 75650                    index++;
 651
 75652                    if (valuesCount - index < 1)
 653                    {
 15654                        throw new InvalidDataException(string.Concat("A ", statement, " spectral statement must specify 
 655                    }
 656
 60657                    color.SpectralFileName = GetNextValue(ref currentLine, ref values).ToString();
 60658                    index++;
 659
 60660                    if (valuesCount > index)
 661                    {
 30662                        color.SpectralFactor = FloatParse(GetNextValue(ref currentLine, ref values));
 30663                        index++;
 664                    }
 665
 30666                    break;
 667
 668                case "xyz":
 60669                    index++;
 670
 60671                    if (valuesCount - index < 1)
 672                    {
 15673                        throw new InvalidDataException(string.Concat("A ", statement, " xyz statement must specify a col
 674                    }
 675
 45676                    color.UseXYZColorSpace = true;
 677
 45678                    var xyz = new ObjVector3();
 679
 45680                    xyz.X = FloatParse(GetNextValue(ref currentLine, ref values));
 45681                    index++;
 682
 45683                    if (valuesCount > index)
 684                    {
 30685                        if (valuesCount - index < 2)
 686                        {
 15687                            throw new InvalidDataException(string.Concat("A ", statement, " xyz statement must specify a
 688                        }
 689
 15690                        xyz.Y = FloatParse(GetNextValue(ref currentLine, ref values));
 15691                        xyz.Z = FloatParse(GetNextValue(ref currentLine, ref values));
 15692                        index += 2;
 693                    }
 694                    else
 695                    {
 15696                        xyz.Y = xyz.X;
 15697                        xyz.Z = xyz.X;
 698                    }
 699
 30700                    color.Color = xyz;
 30701                    break;
 702
 703                default:
 60704                    var rgb = new ObjVector3();
 705
 60706                    rgb.X = FloatParse(value1);
 60707                    index++;
 708
 60709                    if (valuesCount > index)
 710                    {
 45711                        if (valuesCount - index < 2)
 712                        {
 15713                            throw new InvalidDataException(string.Concat("A ", statement, " statement must specify a RGB
 714                        }
 715
 30716                        rgb.Y = FloatParse(GetNextValue(ref currentLine, ref values));
 30717                        rgb.Z = FloatParse(GetNextValue(ref currentLine, ref values));
 30718                        index += 2;
 719                    }
 720                    else
 721                    {
 15722                        rgb.Y = rgb.X;
 15723                        rgb.Z = rgb.X;
 724                    }
 725
 45726                    color.Color = rgb;
 727                    break;
 728            }
 729
 135730            if (index != valuesCount)
 731            {
 15732                throw new InvalidDataException(string.Concat("A ", statement, " statement has too many values."));
 733            }
 734
 120735            return color;
 736        }
 737
 738        private enum MaterialMapType
 739        {
 740            None,
 741            Sphere,
 742            CubeTop,
 743            CubeBottom,
 744            CubeFront,
 745            CubeBack,
 746            CubeLeft,
 747            CubeRight
 748        }
 749
 750        [SuppressMessage("Globalization", "CA1303:Ne pas passer de littéraux en paramètres localisés", Justification = "
 751        private static ObjMaterialMap ParseMaterialMap(ReadOnlySpan<char> statement, ReadOnlySpan<char> value0, ref Read
 752        {
 390753            return ParseMaterialMap(statement, value0, ref currentLine, ref values, valuesCount, out _);
 754        }
 755
 756        [SuppressMessage("Globalization", "CA1303:Ne pas passer de littéraux en paramètres localisés", Justification = "
 757        private static ObjMaterialMap ParseMaterialMap(ReadOnlySpan<char> statement, ReadOnlySpan<char> value0, ref Read
 758        {
 459759            materialMapType = MaterialMapType.None;
 760
 459761            var map = new ObjMaterialMap();
 762
 459763            int valueBufferSize = 16;
 459764            Span<char> valueBuffer = stackalloc char[valueBufferSize];
 765
 1347766            for (int index = 0; index < valuesCount;)
 767            {
 630768                index++;
 769
 630770                if (valuesCount - index < 1)
 771                {
 66772                    throw new InvalidDataException(string.Concat("A ", statement, " statement must specify a filename.")
 773                }
 774
 564775                ReadOnlySpan<char> value1 = GetNextValue(ref currentLine, ref values);
 564776                int value1Length = value1.ToLowerInvariant(valueBuffer);
 777
 778                // Value1Length is -1 when the buffer is too small.
 779                // This should only happen if the value is a file name and not an option
 564780                if (value1Length == -1)
 781                {
 60782                    if (index == 1)
 783                    {
 60784                        if (statement.Equals("refl", StringComparison.OrdinalIgnoreCase))
 785                        {
 0786                            throw new InvalidDataException("A refl statement must specify a type.");
 787                        }
 788                    }
 789
 60790                    var sb = new StringBuilder();
 791
 60792                    sb.Append(value1);
 793
 180794                    for (int i = index + 1; i < valuesCount; i++)
 795                    {
 30796                        sb.Append(' ');
 30797                        sb.Append(GetNextValue(ref currentLine, ref values));
 798                    }
 799
 60800                    string filename = sb.ToString();
 801
 60802                    map.FileName = filename;
 60803                    return map;
 804                }
 805
 504806                if (statement.Equals("refl", StringComparison.OrdinalIgnoreCase))
 807                {
 135808                    if (index == 1)
 809                    {
 69810                        if (!MemoryExtensions.Equals(valueBuffer[..value1Length], "-type", StringComparison.OrdinalIgnor
 811                        {
 3812                            throw new InvalidDataException("A refl statement must specify a type.");
 813                        }
 814                    }
 815                }
 816
 501817                switch (valueBuffer[..value1Length])
 818                {
 819                    case "-type":
 72820                        if (valuesCount - index < 2)
 821                        {
 3822                            throw new InvalidDataException(string.Concat("A ", statement, " -type option must specify a 
 823                        }
 824
 69825                        if (statement.Equals("refl", StringComparison.OrdinalIgnoreCase))
 826                        {
 66827                            ReadOnlySpan<char> value2 = GetNextValue(ref currentLine, ref values);
 66828                            int value2Length = value2.ToLowerInvariant(valueBuffer);
 829
 830                            //if (value2Length == -1)
 831                            //{
 832                            //    throw new InvalidDataException("the buffer is too small");
 833                            //}
 834
 66835                            switch (valueBuffer[..value2Length])
 836                            {
 837                                case "sphere":
 9838                                    materialMapType = MaterialMapType.Sphere;
 9839                                    break;
 840
 841                                case "cube_top":
 9842                                    materialMapType = MaterialMapType.CubeTop;
 9843                                    break;
 844
 845                                case "cube_bottom":
 9846                                    materialMapType = MaterialMapType.CubeBottom;
 9847                                    break;
 848
 849                                case "cube_front":
 9850                                    materialMapType = MaterialMapType.CubeFront;
 9851                                    break;
 852
 853                                case "cube_back":
 9854                                    materialMapType = MaterialMapType.CubeBack;
 9855                                    break;
 856
 857                                case "cube_left":
 9858                                    materialMapType = MaterialMapType.CubeLeft;
 9859                                    break;
 860
 861                                case "cube_right":
 9862                                    materialMapType = MaterialMapType.CubeRight;
 9863                                    break;
 864                            }
 865                        }
 866                        else
 867                        {
 3868                            GetNextValue(ref currentLine, ref values);
 869                        }
 870
 69871                        index++;
 69872                        break;
 873
 874                    case "-blenu":
 875                        {
 15876                            if (valuesCount - index < 2)
 877                            {
 3878                                throw new InvalidDataException(string.Concat("A ", statement, " -blenu option must speci
 879                            }
 880
 12881                            var value2 = GetNextValue(ref currentLine, ref values);
 882
 12883                            if (value2.Equals("on", StringComparison.OrdinalIgnoreCase))
 884                            {
 3885                                map.IsHorizontalBlendingEnabled = true;
 886                            }
 9887                            else if (value2.Equals("off", StringComparison.OrdinalIgnoreCase))
 888                            {
 3889                                map.IsHorizontalBlendingEnabled = false;
 890                            }
 891                            else
 892                            {
 6893                                throw new InvalidDataException(string.Concat("A ", statement, " -blenu option must speci
 894                            }
 895
 6896                            index++;
 6897                            break;
 898                        }
 899
 900                    case "-blenv":
 901                        {
 15902                            if (valuesCount - index < 2)
 903                            {
 3904                                throw new InvalidDataException(string.Concat("A ", statement, " -blenv option must speci
 905                            }
 906
 12907                            var value2 = GetNextValue(ref currentLine, ref values);
 908
 12909                            if (value2.Equals("on", StringComparison.OrdinalIgnoreCase))
 910                            {
 3911                                map.IsVerticalBlendingEnabled = true;
 912                            }
 9913                            else if (value2.Equals("off", StringComparison.OrdinalIgnoreCase))
 914                            {
 3915                                map.IsVerticalBlendingEnabled = false;
 916                            }
 917                            else
 918                            {
 6919                                throw new InvalidDataException(string.Concat("A ", statement, " -blenv option must speci
 920                            }
 921
 6922                            index++;
 6923                            break;
 924                        }
 925
 926                    case "-bm":
 9927                        if (valuesCount - index < 2)
 928                        {
 3929                            throw new InvalidDataException(string.Concat("A ", statement, " -bm option must specify a va
 930                        }
 931
 6932                        map.BumpMultiplier = FloatParse(GetNextValue(ref currentLine, ref values));
 933
 6934                        index++;
 6935                        break;
 936
 937                    case "-boost":
 9938                        if (valuesCount - index < 2)
 939                        {
 3940                            throw new InvalidDataException(string.Concat("A ", statement, " -boost option must specify a
 941                        }
 942
 6943                        map.Boost = FloatParse(GetNextValue(ref currentLine, ref values));
 944
 6945                        index++;
 6946                        break;
 947
 948                    case "-cc":
 949                        {
 15950                            if (valuesCount - index < 2)
 951                            {
 3952                                throw new InvalidDataException(string.Concat("A ", statement, " -cc option must specify 
 953                            }
 954
 12955                            var value2 = GetNextValue(ref currentLine, ref values);
 956
 12957                            if (value2.Equals("on", StringComparison.OrdinalIgnoreCase))
 958                            {
 3959                                map.IsColorCorrectionEnabled = true;
 960                            }
 9961                            else if (value2.Equals("off", StringComparison.OrdinalIgnoreCase))
 962                            {
 3963                                map.IsColorCorrectionEnabled = false;
 964                            }
 965                            else
 966                            {
 6967                                throw new InvalidDataException(string.Concat("A ", statement, " -cc option must specify 
 968                            }
 969
 6970                            index++;
 6971                            break;
 972                        }
 973
 974                    case "-clamp":
 975                        {
 15976                            if (valuesCount - index < 2)
 977                            {
 3978                                throw new InvalidDataException(string.Concat("A ", statement, " -clamp option must speci
 979                            }
 980
 12981                            var value2 = GetNextValue(ref currentLine, ref values);
 982
 12983                            if (value2.Equals("on", StringComparison.OrdinalIgnoreCase))
 984                            {
 3985                                map.IsClampingEnabled = true;
 986                            }
 9987                            else if (value2.Equals("off", StringComparison.OrdinalIgnoreCase))
 988                            {
 3989                                map.IsClampingEnabled = false;
 990                            }
 991                            else
 992                            {
 6993                                throw new InvalidDataException(string.Concat("A ", statement, " -clamp option must speci
 994                            }
 995
 6996                            index++;
 6997                            break;
 998                        }
 999
 1000                    case "-imfchan":
 1001                        {
 271002                            if (valuesCount - index < 2)
 1003                            {
 31004                                throw new InvalidDataException(string.Concat("A ", statement, " -imfchan option must spe
 1005                            }
 1006
 241007                            ReadOnlySpan<char> value2 = GetNextValue(ref currentLine, ref values);
 241008                            int value2Length = value2.ToLowerInvariant(valueBuffer);
 1009
 1010                            //if (value2Length == -1)
 1011                            //{
 1012                            //    throw new InvalidDataException("the buffer is too small");
 1013                            //}
 1014
 241015                            switch (valueBuffer[..value2Length])
 1016                            {
 1017                                case "r":
 31018                                    map.ScalarChannel = ObjMapChannel.Red;
 31019                                    break;
 1020
 1021                                case "g":
 31022                                    map.ScalarChannel = ObjMapChannel.Green;
 31023                                    break;
 1024
 1025                                case "b":
 31026                                    map.ScalarChannel = ObjMapChannel.Blue;
 31027                                    break;
 1028
 1029                                case "m":
 31030                                    map.ScalarChannel = ObjMapChannel.Matte;
 31031                                    break;
 1032
 1033                                case "l":
 31034                                    map.ScalarChannel = ObjMapChannel.Luminance;
 31035                                    break;
 1036
 1037                                case "z":
 31038                                    map.ScalarChannel = ObjMapChannel.Depth;
 31039                                    break;
 1040
 1041                                default:
 61042                                    throw new InvalidDataException(string.Concat("A ", statement, " -imfchan option must
 1043                            }
 1044
 181045                            index++;
 181046                            break;
 1047                        }
 1048
 1049                    case "-mm":
 121050                        if (valuesCount - index < 3)
 1051                        {
 61052                            throw new InvalidDataException(string.Concat("A ", statement, " -mm option must specify a ba
 1053                        }
 1054
 61055                        map.ModifierBase = FloatParse(GetNextValue(ref currentLine, ref values));
 61056                        map.ModifierGain = FloatParse(GetNextValue(ref currentLine, ref values));
 1057
 61058                        index += 2;
 61059                        break;
 1060
 1061                    case "-o":
 151062                        if (valuesCount - index < 2)
 1063                        {
 31064                            throw new InvalidDataException(string.Concat("A ", statement, " -o option must specify at le
 1065                        }
 1066
 121067                        var offset = new ObjVector3();
 1068
 121069                        offset.X = FloatParse(GetNextValue(ref currentLine, ref values));
 1070
 121071                        if (valuesCount - index > 3)
 1072                        {
 61073                            offset.Y = FloatParse(GetNextValue(ref currentLine, ref values));
 1074
 61075                            if (valuesCount - index > 4)
 1076                            {
 31077                                offset.Z = FloatParse(GetNextValue(ref currentLine, ref values));
 31078                                index++;
 1079                            }
 1080
 61081                            index++;
 1082                        }
 1083
 121084                        index++;
 1085
 121086                        map.Offset = offset;
 121087                        break;
 1088
 1089                    case "-s":
 151090                        if (valuesCount - index < 2)
 1091                        {
 31092                            throw new InvalidDataException(string.Concat("A ", statement, " -s option must specify at le
 1093                        }
 1094
 121095                        var scale = new ObjVector3(1.0f, 1.0f, 1.0f);
 1096
 121097                        scale.X = FloatParse(GetNextValue(ref currentLine, ref values));
 1098
 121099                        if (valuesCount - index > 3)
 1100                        {
 61101                            scale.Y = FloatParse(GetNextValue(ref currentLine, ref values));
 1102
 61103                            if (valuesCount - index > 4)
 1104                            {
 31105                                scale.Z = FloatParse(GetNextValue(ref currentLine, ref values));
 31106                                index++;
 1107                            }
 1108
 61109                            index++;
 1110                        }
 1111
 121112                        index++;
 1113
 121114                        map.Scale = scale;
 121115                        break;
 1116
 1117                    case "-t":
 151118                        if (valuesCount - index < 2)
 1119                        {
 31120                            throw new InvalidDataException(string.Concat("A ", statement, " -t option must specify at le
 1121                        }
 1122
 121123                        var turbulence = new ObjVector3();
 1124
 121125                        turbulence.X = FloatParse(GetNextValue(ref currentLine, ref values));
 1126
 121127                        if (valuesCount - index > 3)
 1128                        {
 61129                            turbulence.Y = FloatParse(GetNextValue(ref currentLine, ref values));
 1130
 61131                            if (valuesCount - index > 4)
 1132                            {
 31133                                turbulence.Z = FloatParse(GetNextValue(ref currentLine, ref values));
 31134                                index++;
 1135                            }
 1136
 61137                            index++;
 1138                        }
 1139
 121140                        index++;
 1141
 121142                        map.Turbulence = turbulence;
 121143                        break;
 1144
 1145                    case "-texres":
 91146                        if (valuesCount - index < 2)
 1147                        {
 31148                            throw new InvalidDataException(string.Concat("A ", statement, " -texres option must specify 
 1149                        }
 1150
 61151                        map.TextureResolution = IntParse(GetNextValue(ref currentLine, ref values));
 1152
 61153                        index++;
 61154                        break;
 1155
 1156                    default:
 1157                        {
 2581158                            var sb = new StringBuilder();
 1159
 2581160                            sb.Append(value1);
 1161
 6301162                            for (int i = index + 1; i < valuesCount; i++)
 1163                            {
 571164                                sb.Append(' ');
 571165                                sb.Append(GetNextValue(ref currentLine, ref values));
 1166                            }
 1167
 2581168                            string filename = sb.ToString();
 1169
 2581170                            map.FileName = filename;
 2581171                            index = valuesCount;
 1172
 1173                            break;
 1174                        }
 1175                }
 1176            }
 1177
 2581178            return map;
 1179        }
 1180    }
 1181}
 1182
 1183#endif
 1184

Methods/Properties

MoveNextSkipEmpty(System.MemoryExtensions/SpanSplitEnumerator`1<System.Char>&)
MoveNextSkipEmpty(Polyfills.Polyfill/SpanSplitEnumerator`1<System.Char>&)
GetNextValue(System.ReadOnlySpan`1<System.Char>&,System.MemoryExtensions/SpanSplitEnumerator`1<System.Char>&)
GetNextValue(System.ReadOnlySpan`1<System.Char>&,Polyfills.Polyfill/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>&,System.MemoryExtensions/SpanSplitEnumerator`1<System.Char>&,System.Int32)
ParseMaterialColor(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)
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&)
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&)