Example #1
0
        public static ObjMaterialFile FromStream(Stream stream)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }

            var mtl = new ObjMaterialFile();

            ObjMaterial currentMaterial = null;

            foreach (var values in LineReader.Read(stream))
            {
                switch (values[0].ToLowerInvariant())
                {
                case "newmtl":
                    if (values.Length < 2)
                    {
                        throw new InvalidDataException("A newmtl statement must specify a name.");
                    }

                    if (values.Length != 2)
                    {
                        throw new InvalidDataException("A newmtl statement has too many values.");
                    }

                    currentMaterial = new ObjMaterial
                    {
                        Name = values[1]
                    };

                    mtl.Materials.Add(currentMaterial);

                    break;

                case "ka":
                    if (currentMaterial == null)
                    {
                        throw new InvalidDataException("The material name is not specified.");
                    }

                    currentMaterial.AmbientColor = ObjMaterialFileReader.ParseMaterialColor("Ka", values);
                    break;

                case "kd":
                    if (currentMaterial == null)
                    {
                        throw new InvalidDataException("The material name is not specified.");
                    }

                    currentMaterial.DiffuseColor = ObjMaterialFileReader.ParseMaterialColor("Kd", values);
                    break;

                case "ke":
                    if (currentMaterial == null)
                    {
                        throw new InvalidDataException("The material name is not specified.");
                    }

                    currentMaterial.EmissiveColor = ObjMaterialFileReader.ParseMaterialColor("Ke", values);
                    break;

                case "ks":
                    if (currentMaterial == null)
                    {
                        throw new InvalidDataException("The material name is not specified.");
                    }

                    currentMaterial.SpecularColor = ObjMaterialFileReader.ParseMaterialColor("Ks", values);
                    break;

                case "tf":
                    if (currentMaterial == null)
                    {
                        throw new InvalidDataException("The material name is not specified.");
                    }

                    currentMaterial.TransmissionColor = ObjMaterialFileReader.ParseMaterialColor("Tf", values);
                    break;

                case "illum":
                    if (currentMaterial == null)
                    {
                        throw new InvalidDataException("The material name is not specified.");
                    }

                    if (values.Length < 2)
                    {
                        throw new InvalidDataException("An illum statement must specify an illumination model.");
                    }

                    if (values.Length != 2)
                    {
                        throw new InvalidDataException("An illum statement has too many values.");
                    }

                    currentMaterial.IlluminationModel = int.Parse(values[1], CultureInfo.InvariantCulture);
                    break;

                case "d":
                    if (currentMaterial == null)
                    {
                        throw new InvalidDataException("The material name is not specified.");
                    }

                    if (values.Length < 2)
                    {
                        throw new InvalidDataException("A d statement must specify a factor.");
                    }

                    if (string.Equals(values[1], "-halo", StringComparison.OrdinalIgnoreCase))
                    {
                        if (values.Length < 3)
                        {
                            throw new InvalidDataException("A d statement must specify a factor.");
                        }

                        if (values.Length != 3)
                        {
                            throw new InvalidDataException("A d statement has too many values.");
                        }

                        currentMaterial.IsHaloDissolve = true;
                        currentMaterial.DissolveFactor = float.Parse(values[2], CultureInfo.InvariantCulture);
                    }
                    else
                    {
                        if (values.Length != 2)
                        {
                            throw new InvalidDataException("A d statement has too many values.");
                        }

                        currentMaterial.DissolveFactor = float.Parse(values[1], CultureInfo.InvariantCulture);
                    }

                    break;

                case "ns":
                    if (currentMaterial == null)
                    {
                        throw new InvalidDataException("The material name is not specified.");
                    }

                    if (values.Length < 2)
                    {
                        throw new InvalidDataException("A Ns statement must specify a specular exponent.");
                    }

                    if (values.Length != 2)
                    {
                        throw new InvalidDataException("A Ns statement has too many values.");
                    }

                    currentMaterial.SpecularExponent = float.Parse(values[1], CultureInfo.InvariantCulture);
                    break;

                case "sharpness":
                    if (currentMaterial == null)
                    {
                        throw new InvalidDataException("The material name is not specified.");
                    }

                    if (values.Length < 2)
                    {
                        throw new InvalidDataException("A sharpness statement must specify a sharpness value.");
                    }

                    if (values.Length != 2)
                    {
                        throw new InvalidDataException("A sharpness statement has too many values.");
                    }

                    currentMaterial.Sharpness = int.Parse(values[1], CultureInfo.InvariantCulture);
                    break;

                case "ni":
                    if (currentMaterial == null)
                    {
                        throw new InvalidDataException("The material name is not specified.");
                    }

                    if (values.Length < 2)
                    {
                        throw new InvalidDataException("A Ni statement must specify an optical density.");
                    }

                    if (values.Length != 2)
                    {
                        throw new InvalidDataException("A Ni statement has too many values.");
                    }

                    currentMaterial.OpticalDensity = float.Parse(values[1], CultureInfo.InvariantCulture);
                    break;

                case "map_aat":
                    if (currentMaterial == null)
                    {
                        throw new InvalidDataException("The material name is not specified.");
                    }

                    if (values.Length < 2)
                    {
                        throw new InvalidDataException("A map_aat statement must specify a value.");
                    }

                    if (values.Length != 2)
                    {
                        throw new InvalidDataException("A map_aat statement has too many values.");
                    }

                    if (string.Equals(values[1], "on", StringComparison.OrdinalIgnoreCase))
                    {
                        currentMaterial.IsAntiAliasingEnabled = true;
                    }
                    else if (string.Equals(values[1], "off", StringComparison.OrdinalIgnoreCase))
                    {
                        currentMaterial.IsAntiAliasingEnabled = false;
                    }
                    else
                    {
                        throw new InvalidDataException("A map_aat statement must specify on or off.");
                    }

                    break;

                case "map_ka":
                    if (currentMaterial == null)
                    {
                        throw new InvalidDataException("The material name is not specified.");
                    }

                    currentMaterial.AmbientMap = ObjMaterialFileReader.ParseMaterialMap("map_Ka", values);
                    break;

                case "map_kd":
                    if (currentMaterial == null)
                    {
                        throw new InvalidDataException("The material name is not specified.");
                    }

                    currentMaterial.DiffuseMap = ObjMaterialFileReader.ParseMaterialMap("map_Kd", values);
                    break;

                case "map_ke":
                    if (currentMaterial == null)
                    {
                        throw new InvalidDataException("The material name is not specified.");
                    }

                    currentMaterial.EmissiveMap = ObjMaterialFileReader.ParseMaterialMap("map_Ke", values);
                    break;

                case "map_ks":
                    if (currentMaterial == null)
                    {
                        throw new InvalidDataException("The material name is not specified.");
                    }

                    currentMaterial.SpecularMap = ObjMaterialFileReader.ParseMaterialMap("map_Ks", values);
                    break;

                case "map_ns":
                    if (currentMaterial == null)
                    {
                        throw new InvalidDataException("The material name is not specified.");
                    }

                    currentMaterial.SpecularExponentMap = ObjMaterialFileReader.ParseMaterialMap("map_Ns", values);
                    break;

                case "map_d":
                case "map_tr":
                    if (currentMaterial == null)
                    {
                        throw new InvalidDataException("The material name is not specified.");
                    }

                    currentMaterial.DissolveMap = ObjMaterialFileReader.ParseMaterialMap("map_d", values);
                    break;

                case "decal":
                case "map_decal":
                    if (currentMaterial == null)
                    {
                        throw new InvalidDataException("The material name is not specified.");
                    }

                    currentMaterial.DecalMap = ObjMaterialFileReader.ParseMaterialMap("decal", values);
                    break;

                case "disp":
                case "map_disp":
                    if (currentMaterial == null)
                    {
                        throw new InvalidDataException("The material name is not specified.");
                    }

                    currentMaterial.DispMap = ObjMaterialFileReader.ParseMaterialMap("disp", values);
                    break;

                case "bump":
                case "map_bump":
                    if (currentMaterial == null)
                    {
                        throw new InvalidDataException("The material name is not specified.");
                    }

                    currentMaterial.BumpMap = ObjMaterialFileReader.ParseMaterialMap("bump", values);
                    break;

                case "refl":
                case "map_refl":
                    if (currentMaterial == null)
                    {
                        throw new InvalidDataException("The material name is not specified.");
                    }

                    if (values.Length < 4)
                    {
                        throw new InvalidDataException("A refl statement must specify a type and a file name.");
                    }

                    if (!string.Equals(values[1], "-type", StringComparison.OrdinalIgnoreCase))
                    {
                        throw new InvalidDataException("A refl statement must specify a type.");
                    }

                    switch (values[2].ToLowerInvariant())
                    {
                    case "sphere":
                        currentMaterial.ReflectionMap.Sphere = ObjMaterialFileReader.ParseMaterialMap("refl", values);
                        break;

                    case "cube_top":
                        currentMaterial.ReflectionMap.CubeTop = ObjMaterialFileReader.ParseMaterialMap("refl", values);
                        break;

                    case "cube_bottom":
                        currentMaterial.ReflectionMap.CubeBottom = ObjMaterialFileReader.ParseMaterialMap("refl", values);
                        break;

                    case "cube_front":
                        currentMaterial.ReflectionMap.CubeFront = ObjMaterialFileReader.ParseMaterialMap("refl", values);
                        break;

                    case "cube_back":
                        currentMaterial.ReflectionMap.CubeBack = ObjMaterialFileReader.ParseMaterialMap("refl", values);
                        break;

                    case "cube_left":
                        currentMaterial.ReflectionMap.CubeLeft = ObjMaterialFileReader.ParseMaterialMap("refl", values);
                        break;

                    case "cube_right":
                        currentMaterial.ReflectionMap.CubeRight = ObjMaterialFileReader.ParseMaterialMap("refl", values);
                        break;
                    }

                    break;
                }
            }

            return(mtl);
        }