protected virtual void MapOptionT(IMaterialMapState state, MaterialMapToken token, string[] values)
        {
            if (values.Length - state.Index < 2)
            {
                throw new InvalidDataException(string.Format("The <{0}> -{1} option must specify at least 2 values. Line: {2}.", state.Token, token, state.LineNumber));
            }

            var turbulence = new XYZ()
            {
                X = float.Parse(values[state.Index + 1], CultureInfo.InvariantCulture)
            };

            if (values.Length - state.Index > 3)
            {
                turbulence.Y = float.Parse(values[state.Index + 2], CultureInfo.InvariantCulture);

                if (values.Length - state.Index > 4)
                {
                    turbulence.Z = float.Parse(values[state.Index + 3], CultureInfo.InvariantCulture);
                    state.Index++;
                }

                state.Index++;
            }

            state.Index++;

            state.Map.Turbulence = turbulence;
        }
        protected virtual void MapOptionType(IMaterialMapState state, MaterialMapToken token, string[] values)
        {
            if (values.Length - state.Index < 2)
            {
                throw new InvalidDataException(string.Format("The <{0}> -{1} option must specify a value. Line: {2}.", state.Token, token, state.LineNumber));
            }

            state.Index++;
        }
        protected virtual void MapOptionTexRes(IMaterialMapState state, MaterialMapToken token, string[] values)
        {
            if (values.Length - state.Index < 2)
            {
                throw new InvalidDataException(string.Format("The <{0}> -{1} option must specify a values. Line: {2}.", state.Token, token, state.LineNumber));
            }

            state.Map.TextureResolution = int.Parse(values[state.Index + 1], CultureInfo.InvariantCulture);

            state.Index++;
        }
        protected virtual void MapOptionMM(IMaterialMapState state, MaterialMapToken token, string[] values)
        {
            if (values.Length - state.Index < 3)
            {
                throw new InvalidDataException(string.Format("The <{0}> -{1} option must specify a base and a gain. Line: {2}.", state.Token, token, state.LineNumber));
            }

            state.Map.ModifierBase = float.Parse(values[state.Index + 1], CultureInfo.InvariantCulture);
            state.Map.ModifierGain = float.Parse(values[state.Index + 2], CultureInfo.InvariantCulture);

            state.Index += 2;
        }
        protected virtual void MapOptionImfChan(IMaterialMapState state, MaterialMapToken token, string[] values)
        {
            if (values.Length - state.Index < 2)
            {
                throw new InvalidDataException(string.Format("The <{0}> -{1} option must specify a value. Line: {2}.", state.Token, token, state.LineNumber));
            }

            if (!Enum.TryParse <IMFChanToken>(values[state.Index + 1], true, out var imfChanToken))
            {
                throw new InvalidDataException(string.Format("The <{0}> -{1} option must specify a value in ({2}).", state.Token, token, string.Join(", ", Enum.GetValues(typeof(IMFChanToken)))));
            }

            switch (imfChanToken)
            {
            case IMFChanToken.R:
            {
                state.Map.ScalarChannel = MapChannel.Red;
                break;
            }

            case IMFChanToken.G:
            {
                state.Map.ScalarChannel = MapChannel.Green;
                break;
            }

            case IMFChanToken.B:
            {
                state.Map.ScalarChannel = MapChannel.Blue;
                break;
            }

            case IMFChanToken.M:
            {
                state.Map.ScalarChannel = MapChannel.Matte;
                break;
            }

            case IMFChanToken.L:
            {
                state.Map.ScalarChannel = MapChannel.Luminance;
                break;
            }

            case IMFChanToken.Z:
            {
                state.Map.ScalarChannel = MapChannel.Depth;
                break;
            }
            }

            state.Index++;
        }
        protected virtual void MapOptionClamp(IMaterialMapState state, MaterialMapToken token, string[] values)
        {
            if (values.Length - state.Index < 2)
            {
                throw new InvalidDataException(string.Format("The <{0}> -{1} option must specify a value. Line: {2}.", state.Token, token, state.LineNumber));
            }

            if (!Enum.TryParse <OnOff>(values[1], true, out var onOffValue))
            {
                throw new InvalidDataException(string.Format("The <{0}> -{1} option must specify on or off. Line: {2}.", state.Token, token, state.LineNumber));
            }

            state.Map.IsClampingEnabled = onOffValue == OnOff.On;

            state.Index++;
        }