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

            var obj     = new ObjFile();
            var context = new ObjFileReaderContext(obj);

            foreach (var values in LineReader.Read(stream))
            {
                switch (values[0].ToLowerInvariant())
                {
                case "v":
                {
                    if (values.Length < 4)
                    {
                        throw new InvalidDataException("A v statement must specify at least 3 values.");
                    }

                    float x        = float.Parse(values[1], CultureInfo.InvariantCulture);
                    float y        = float.Parse(values[2], CultureInfo.InvariantCulture);
                    float z        = float.Parse(values[3], CultureInfo.InvariantCulture);
                    float w        = 1.0f;
                    bool  hasColor = false;
                    float r        = 0.0f;
                    float g        = 0.0f;
                    float b        = 0.0f;
                    float a        = 1.0f;

                    if (values.Length == 4 || values.Length == 5)
                    {
                        if (values.Length == 5)
                        {
                            w = float.Parse(values[4], CultureInfo.InvariantCulture);
                        }
                    }
                    else if (values.Length == 7 || values.Length == 8)
                    {
                        hasColor = true;
                        r        = float.Parse(values[4], CultureInfo.InvariantCulture);
                        g        = float.Parse(values[5], CultureInfo.InvariantCulture);
                        b        = float.Parse(values[6], CultureInfo.InvariantCulture);

                        if (values.Length == 8)
                        {
                            a = float.Parse(values[7], CultureInfo.InvariantCulture);
                        }
                    }
                    else
                    {
                        throw new InvalidDataException("A v statement has too many values.");
                    }

                    var v = new ObjVertex();
                    v.Position = new ObjVector4(x, y, z, w);

                    if (hasColor)
                    {
                        v.Color = new ObjVector4(r, g, b, a);
                    }

                    obj.Vertices.Add(v);
                    break;
                }

                case "vp":
                {
                    if (values.Length < 2)
                    {
                        throw new InvalidDataException("A vp statement must specify at least 1 value.");
                    }

                    var v = new ObjVector3();
                    v.X = float.Parse(values[1], CultureInfo.InvariantCulture);

                    if (values.Length == 2)
                    {
                        v.Y = 0.0f;
                        v.Z = 1.0f;
                    }
                    else if (values.Length == 3)
                    {
                        v.Y = float.Parse(values[2], CultureInfo.InvariantCulture);
                        v.Z = 1.0f;
                    }
                    else if (values.Length == 4)
                    {
                        v.Y = float.Parse(values[2], CultureInfo.InvariantCulture);
                        v.Z = float.Parse(values[3], CultureInfo.InvariantCulture);
                    }
                    else
                    {
                        throw new InvalidDataException("A vp statement has too many values.");
                    }

                    obj.ParameterSpaceVertices.Add(v);
                    break;
                }

                case "vn":
                {
                    if (values.Length < 4)
                    {
                        throw new InvalidDataException("A vn statement must specify 3 values.");
                    }

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

                    var v = new ObjVector3();
                    v.X = float.Parse(values[1], CultureInfo.InvariantCulture);
                    v.Y = float.Parse(values[2], CultureInfo.InvariantCulture);
                    v.Z = float.Parse(values[3], CultureInfo.InvariantCulture);

                    obj.VertexNormals.Add(v);
                    break;
                }

                case "vt":
                {
                    if (values.Length < 2)
                    {
                        throw new InvalidDataException("A vt statement must specify at least 1 value.");
                    }

                    var v = new ObjVector3();
                    v.X = float.Parse(values[1], CultureInfo.InvariantCulture);

                    if (values.Length == 2)
                    {
                        v.Y = 0.0f;
                        v.Z = 0.0f;
                    }
                    else if (values.Length == 3)
                    {
                        v.Y = float.Parse(values[2], CultureInfo.InvariantCulture);
                        v.Z = 0.0f;
                    }
                    else if (values.Length == 4)
                    {
                        v.Y = float.Parse(values[2], CultureInfo.InvariantCulture);
                        v.Z = float.Parse(values[3], CultureInfo.InvariantCulture);
                    }
                    else
                    {
                        throw new InvalidDataException("A vt statement has too many values.");
                    }

                    obj.TextureVertices.Add(v);
                    break;
                }

                case "cstype":
                    ObjFileReader.ParseFreeFormType(context, values);
                    break;

                case "deg":
                    if (values.Length < 2)
                    {
                        throw new InvalidDataException("A deg statement must specify at least 1 value.");
                    }

                    if (values.Length == 2)
                    {
                        context.DegreeU = int.Parse(values[1]);
                        context.DegreeV = 0;
                    }
                    else if (values.Length == 3)
                    {
                        context.DegreeU = int.Parse(values[1], CultureInfo.InvariantCulture);
                        context.DegreeV = int.Parse(values[2], CultureInfo.InvariantCulture);
                    }
                    else
                    {
                        throw new InvalidDataException("A deg statement has too many values.");
                    }

                    break;

                case "bmat":
                {
                    if (values.Length < 2)
                    {
                        throw new InvalidDataException("A bmat statement must specify a direction.");
                    }

                    int d;

                    if (string.Equals(values[1], "u", StringComparison.OrdinalIgnoreCase))
                    {
                        d = 1;
                    }
                    else if (string.Equals(values[1], "v", StringComparison.OrdinalIgnoreCase))
                    {
                        d = 2;
                    }
                    else
                    {
                        throw new InvalidDataException("A bmat statement has an unknown direction.");
                    }

                    int count = (context.DegreeU + 1) * (context.DegreeV + 1);

                    if (values.Length != count + 2)
                    {
                        throw new InvalidDataException("A bmat statement has too many or too few values.");
                    }

                    var matrix = new float[count];

                    for (int i = 0; i < count; i++)
                    {
                        matrix[i] = float.Parse(values[2 + i], CultureInfo.InvariantCulture);
                    }

                    switch (d)
                    {
                    case 1:
                        context.BasicMatrixU = matrix;
                        break;

                    case 2:
                        context.BasicMatrixV = matrix;
                        break;
                    }

                    break;
                }

                case "step":
                    if (values.Length < 2)
                    {
                        throw new InvalidDataException("A step statement must specify at least 1 value.");
                    }

                    if (values.Length == 2)
                    {
                        context.StepU = float.Parse(values[1], CultureInfo.InvariantCulture);
                        context.StepV = 1.0f;
                    }
                    else if (values.Length == 3)
                    {
                        context.StepU = float.Parse(values[1], CultureInfo.InvariantCulture);
                        context.StepV = float.Parse(values[2], CultureInfo.InvariantCulture);
                    }
                    else
                    {
                        throw new InvalidDataException("A step statement has too many values.");
                    }

                    break;

                case "p":
                {
                    if (values.Length < 2)
                    {
                        throw new InvalidDataException("A p statement must specify at least 1 value.");
                    }

                    var point = new ObjPoint();

                    for (int i = 1; i < values.Length; i++)
                    {
                        point.Vertices.Add(ObjFileReader.ParseTriplet(obj, values[i]));
                    }

                    context.ApplyAttributesToElement(point);
                    context.ApplyAttributesToPolygonalElement(point);

                    obj.Points.Add(point);

                    foreach (var group in context.GetCurrentGroups())
                    {
                        group.Points.Add(point);
                    }

                    break;
                }

                case "l":
                {
                    if (values.Length < 3)
                    {
                        throw new InvalidDataException("A l statement must specify at least 2 values.");
                    }

                    var line = new ObjLine();

                    for (int i = 1; i < values.Length; i++)
                    {
                        line.Vertices.Add(ObjFileReader.ParseTriplet(obj, values[i]));
                    }

                    context.ApplyAttributesToElement(line);
                    context.ApplyAttributesToPolygonalElement(line);

                    obj.Lines.Add(line);

                    foreach (var group in context.GetCurrentGroups())
                    {
                        group.Lines.Add(line);
                    }

                    break;
                }

                case "f":
                case "fo":
                {
                    if (values.Length < 4)
                    {
                        throw new InvalidDataException("A f statement must specify at least 3 values.");
                    }

                    var face = new ObjFace();

                    for (int i = 1; i < values.Length; i++)
                    {
                        face.Vertices.Add(ObjFileReader.ParseTriplet(obj, values[i]));
                    }

                    context.ApplyAttributesToElement(face);
                    context.ApplyAttributesToPolygonalElement(face);

                    obj.Faces.Add(face);

                    foreach (var group in context.GetCurrentGroups())
                    {
                        group.Faces.Add(face);
                    }

                    break;
                }

                case "curv":
                {
                    if (values.Length < 5)
                    {
                        throw new InvalidDataException("A curv statement must specify at least 4 values.");
                    }

                    var curve = new ObjCurve();

                    curve.StartParameter = float.Parse(values[1], CultureInfo.InvariantCulture);
                    curve.EndParameter   = float.Parse(values[2], CultureInfo.InvariantCulture);

                    for (int i = 3; i < values.Length; i++)
                    {
                        int v = int.Parse(values[i], CultureInfo.InvariantCulture);

                        if (v == 0)
                        {
                            throw new InvalidDataException("A curv statement contains an invalid vertex index.");
                        }

                        if (v < 0)
                        {
                            v = obj.Vertices.Count + v + 1;
                        }

                        if (v <= 0 || v > obj.Vertices.Count)
                        {
                            throw new IndexOutOfRangeException();
                        }

                        curve.Vertices.Add(v);
                    }

                    context.ApplyAttributesToElement(curve);
                    context.ApplyAttributesToFreeFormElement(curve);
                    context.CurrentFreeFormElement = curve;

                    obj.Curves.Add(curve);

                    foreach (var group in context.GetCurrentGroups())
                    {
                        group.Curves.Add(curve);
                    }

                    break;
                }

                case "curv2":
                {
                    if (values.Length < 3)
                    {
                        throw new InvalidDataException("A curv2 statement must specify at least 2 values.");
                    }

                    var curve = new ObjCurve2D();

                    for (int i = 1; i < values.Length; i++)
                    {
                        int vp = int.Parse(values[i], CultureInfo.InvariantCulture);

                        if (vp == 0)
                        {
                            throw new InvalidDataException("A curv2 statement contains an invalid parameter space vertex index.");
                        }

                        if (vp < 0)
                        {
                            vp = obj.ParameterSpaceVertices.Count + vp + 1;
                        }

                        if (vp <= 0 || vp > obj.ParameterSpaceVertices.Count)
                        {
                            throw new IndexOutOfRangeException();
                        }

                        curve.ParameterSpaceVertices.Add(vp);
                    }

                    context.ApplyAttributesToElement(curve);
                    context.ApplyAttributesToFreeFormElement(curve);
                    context.CurrentFreeFormElement = curve;

                    obj.Curves2D.Add(curve);

                    foreach (var group in context.GetCurrentGroups())
                    {
                        group.Curves2D.Add(curve);
                    }

                    break;
                }

                case "surf":
                {
                    if (values.Length < 6)
                    {
                        throw new InvalidDataException("A surf statement must specify at least 5 values.");
                    }

                    var surface = new ObjSurface();

                    surface.StartParameterU = float.Parse(values[1], CultureInfo.InvariantCulture);
                    surface.EndParameterU   = float.Parse(values[2], CultureInfo.InvariantCulture);
                    surface.StartParameterV = float.Parse(values[3], CultureInfo.InvariantCulture);
                    surface.EndParameterV   = float.Parse(values[4], CultureInfo.InvariantCulture);

                    for (int i = 5; i < values.Length; i++)
                    {
                        surface.Vertices.Add(ObjFileReader.ParseTriplet(obj, values[i]));
                    }

                    context.ApplyAttributesToElement(surface);
                    context.ApplyAttributesToFreeFormElement(surface);
                    context.CurrentFreeFormElement = surface;

                    obj.Surfaces.Add(surface);

                    foreach (var group in context.GetCurrentGroups())
                    {
                        group.Surfaces.Add(surface);
                    }

                    break;
                }

                case "parm":
                    if (context.CurrentFreeFormElement == null)
                    {
                        break;
                    }

                    if (values.Length < 4)
                    {
                        throw new InvalidDataException("A parm statement must specify at least 3 values.");
                    }

                    IList <float> parameters;

                    if (string.Equals(values[1], "u", StringComparison.OrdinalIgnoreCase))
                    {
                        parameters = context.CurrentFreeFormElement.ParametersU;
                    }
                    else if (string.Equals(values[1], "v", StringComparison.OrdinalIgnoreCase))
                    {
                        parameters = context.CurrentFreeFormElement.ParametersV;
                    }
                    else
                    {
                        throw new InvalidDataException("A parm statement has an unknown direction.");
                    }

                    for (int i = 2; i < values.Length; i++)
                    {
                        parameters.Add(float.Parse(values[i], CultureInfo.InvariantCulture));
                    }

                    break;

                case "trim":
                    if (context.CurrentFreeFormElement == null)
                    {
                        break;
                    }

                    ObjFileReader.ParseCurveIndex(context.CurrentFreeFormElement.OuterTrimmingCurves, obj, values);
                    break;

                case "hole":
                    if (context.CurrentFreeFormElement == null)
                    {
                        break;
                    }

                    ObjFileReader.ParseCurveIndex(context.CurrentFreeFormElement.InnerTrimmingCurves, obj, values);
                    break;

                case "scrv":
                    if (context.CurrentFreeFormElement == null)
                    {
                        break;
                    }

                    ObjFileReader.ParseCurveIndex(context.CurrentFreeFormElement.SequenceCurves, obj, values);
                    break;

                case "sp":
                    if (context.CurrentFreeFormElement == null)
                    {
                        break;
                    }

                    if (values.Length < 2)
                    {
                        throw new InvalidDataException("A sp statement must specify at least 1 value.");
                    }

                    for (int i = 1; i < values.Length; i++)
                    {
                        int vp = int.Parse(values[i], CultureInfo.InvariantCulture);

                        if (vp == 0)
                        {
                            throw new InvalidDataException("A sp statement contains an invalid parameter space vertex index.");
                        }

                        if (vp < 0)
                        {
                            vp = obj.ParameterSpaceVertices.Count + vp + 1;
                        }

                        if (vp <= 0 || vp > obj.ParameterSpaceVertices.Count)
                        {
                            throw new IndexOutOfRangeException();
                        }

                        context.CurrentFreeFormElement.SpecialPoints.Add(vp);
                    }

                    break;

                case "end":
                    context.CurrentFreeFormElement = null;
                    break;

                case "con":
                    ObjFileReader.ParseSurfaceConnection(obj, values);
                    break;

                case "g":
                    ObjFileReader.ParseGroupName(values, context);
                    break;

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

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

                    if (string.Equals(values[1], "off", StringComparison.OrdinalIgnoreCase))
                    {
                        context.SmoothingGroupNumber = 0;
                    }
                    else
                    {
                        context.SmoothingGroupNumber = int.Parse(values[1], CultureInfo.InvariantCulture);
                    }

                    break;

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

                    if (string.Equals(values[1], "off", StringComparison.OrdinalIgnoreCase))
                    {
                        context.MergingGroupNumber = 0;
                    }
                    else
                    {
                        context.MergingGroupNumber = int.Parse(values[1], CultureInfo.InvariantCulture);
                    }

                    if (context.MergingGroupNumber == 0)
                    {
                        if (values.Length > 3)
                        {
                            throw new InvalidDataException("A mg statement has too many values.");
                        }
                    }
                    else
                    {
                        if (values.Length != 3)
                        {
                            throw new InvalidDataException("A mg statement has too many or too few values.");
                        }

                        float res = float.Parse(values[2], CultureInfo.InvariantCulture);

                        obj.MergingGroupResolutions[context.MergingGroupNumber] = res;
                    }

                    break;

                case "o":
                    if (values.Length == 1)
                    {
                        context.ObjectName = null;
                        break;
                    }

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

                    context.ObjectName = values[1];
                    break;

                case "bevel":
                    if (values.Length < 2)
                    {
                        throw new InvalidDataException("A bevel statement must specify a name.");
                    }

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

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

                    break;

                case "c_interp":
                    if (values.Length < 2)
                    {
                        throw new InvalidDataException("A c_interp statement must specify a name.");
                    }

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

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

                    break;

                case "d_interp":
                    if (values.Length < 2)
                    {
                        throw new InvalidDataException("A d_interp statement must specify a name.");
                    }

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

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

                    break;

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

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

                    context.LevelOfDetail = int.Parse(values[1], CultureInfo.InvariantCulture);
                    break;

                case "maplib":
                    if (values.Length < 2)
                    {
                        throw new InvalidDataException("A maplib statement must specify a file name.");
                    }

                    for (int i = 1; i < values.Length; i++)
                    {
                        if (!Path.HasExtension(values[i]))
                        {
                            throw new InvalidDataException("A file name must have an extension.");
                        }

                        obj.MapLibraries.Add(values[i]);
                    }

                    break;

                case "mtllib":
                    if (values.Length < 2)
                    {
                        throw new InvalidDataException("A mtllib statement must specify a file name.");
                    }

                    for (int i = 1; i < values.Length; i++)
                    {
                        if (!Path.HasExtension(values[i]))
                        {
                            throw new InvalidDataException("A file name must have an extension.");
                        }

                        obj.MaterialLibraries.Add(values[i]);
                    }

                    break;

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

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

                    if (string.Equals(values[1], "off", StringComparison.OrdinalIgnoreCase))
                    {
                        context.MapName = null;
                    }
                    else
                    {
                        context.MapName = values[1];
                    }

                    break;

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

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

                    if (string.Equals(values[1], "off", StringComparison.OrdinalIgnoreCase))
                    {
                        context.MaterialName = null;
                    }
                    else
                    {
                        context.MaterialName = values[1];
                    }

                    break;

                case "shadow_obj":
                    if (values.Length < 2)
                    {
                        throw new InvalidDataException("A shadow_obj statement must specify a file name.");
                    }

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

                    if (!Path.HasExtension(values[1]))
                    {
                        throw new InvalidDataException("A file name must have an extension.");
                    }

                    obj.ShadowObjectFileName = values[1];
                    break;

                case "trace_obj":
                    if (values.Length < 2)
                    {
                        throw new InvalidDataException("A trace_obj statement must specify a file name.");
                    }

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

                    if (!Path.HasExtension(values[1]))
                    {
                        throw new InvalidDataException("A file name must have an extension.");
                    }

                    obj.TraceObjectFileName = values[1];
                    break;

                case "ctech":
                    context.CurveApproximationTechnique = ObjFileReader.ParseApproximationTechnique(values);
                    break;

                case "stech":
                    context.SurfaceApproximationTechnique = ObjFileReader.ParseApproximationTechnique(values);
                    break;

                case "bsp":
                case "bzp":
                case "cdc":
                case "cdp":
                case "res":
                    throw new NotImplementedException(string.Concat(values[0], " statement have been replaced by free-form geometry statements."));
                }
            }

            return(obj);
        }
Example #2
0
        private static ObjMaterialMap ParseMaterialMap(string statement, string[] values)
        {
            var map = new ObjMaterialMap();

            for (int index = 0; index < values.Length;)
            {
                index++;

                if (values.Length - index < 1)
                {
                    throw new InvalidDataException(string.Concat("A ", statement, " statement must specify a filename."));
                }

                switch (values[index].ToLowerInvariant())
                {
                case "-type":
                    if (values.Length - index < 2)
                    {
                        throw new InvalidDataException(string.Concat("A ", statement, " -type option must specify a value."));
                    }

                    index++;
                    break;

                case "-blenu":
                    if (values.Length - index < 2)
                    {
                        throw new InvalidDataException(string.Concat("A ", statement, " -blenu option must specify a value."));
                    }

                    if (string.Equals(values[index + 1], "on", StringComparison.OrdinalIgnoreCase))
                    {
                        map.IsHorizontalBlendingEnabled = true;
                    }
                    else if (string.Equals(values[index + 1], "off", StringComparison.OrdinalIgnoreCase))
                    {
                        map.IsHorizontalBlendingEnabled = false;
                    }
                    else
                    {
                        throw new InvalidDataException(string.Concat("A ", statement, " -blenu option must specify on or off."));
                    }

                    index++;
                    break;

                case "-blenv":
                    if (values.Length - index < 2)
                    {
                        throw new InvalidDataException(string.Concat("A ", statement, " -blenv option must specify a value."));
                    }

                    if (string.Equals(values[index + 1], "on", StringComparison.OrdinalIgnoreCase))
                    {
                        map.IsVerticalBlendingEnabled = true;
                    }
                    else if (string.Equals(values[index + 1], "off", StringComparison.OrdinalIgnoreCase))
                    {
                        map.IsVerticalBlendingEnabled = false;
                    }
                    else
                    {
                        throw new InvalidDataException(string.Concat("A ", statement, " -blenv option must specify on or off."));
                    }

                    index++;
                    break;

                case "-bm":
                    if (values.Length - index < 2)
                    {
                        throw new InvalidDataException(string.Concat("A ", statement, " -bm option must specify a value."));
                    }

                    map.BumpMultiplier = float.Parse(values[index + 1], CultureInfo.InvariantCulture);

                    index++;
                    break;

                case "-boost":
                    if (values.Length - index < 2)
                    {
                        throw new InvalidDataException(string.Concat("A ", statement, " -boost option must specify a value."));
                    }

                    map.Boost = float.Parse(values[index + 1], CultureInfo.InvariantCulture);

                    index++;
                    break;

                case "-cc":
                    if (values.Length - index < 2)
                    {
                        throw new InvalidDataException(string.Concat("A ", statement, " -cc option must specify a value."));
                    }

                    if (string.Equals(values[index + 1], "on", StringComparison.OrdinalIgnoreCase))
                    {
                        map.IsColorCorrectionEnabled = true;
                    }
                    else if (string.Equals(values[index + 1], "off", StringComparison.OrdinalIgnoreCase))
                    {
                        map.IsColorCorrectionEnabled = false;
                    }
                    else
                    {
                        throw new InvalidDataException(string.Concat("A ", statement, " -cc option must specify on or off."));
                    }

                    index++;
                    break;

                case "-clamp":
                    if (values.Length - index < 2)
                    {
                        throw new InvalidDataException(string.Concat("A ", statement, " -clamp option must specify a value."));
                    }

                    if (string.Equals(values[index + 1], "on", StringComparison.OrdinalIgnoreCase))
                    {
                        map.IsClampingEnabled = true;
                    }
                    else if (string.Equals(values[index + 1], "off", StringComparison.OrdinalIgnoreCase))
                    {
                        map.IsClampingEnabled = false;
                    }
                    else
                    {
                        throw new InvalidDataException(string.Concat("A ", statement, " -clamp option must specify on or off."));
                    }

                    index++;
                    break;

                case "-imfchan":
                    if (values.Length - index < 2)
                    {
                        throw new InvalidDataException(string.Concat("A ", statement, " -imfchan option must specify a value."));
                    }

                    switch (values[index + 1].ToLowerInvariant())
                    {
                    case "r":
                        map.ScalarChannel = ObjMapChannel.Red;
                        break;

                    case "g":
                        map.ScalarChannel = ObjMapChannel.Green;
                        break;

                    case "b":
                        map.ScalarChannel = ObjMapChannel.Blue;
                        break;

                    case "m":
                        map.ScalarChannel = ObjMapChannel.Matte;
                        break;

                    case "l":
                        map.ScalarChannel = ObjMapChannel.Luminance;
                        break;

                    case "z":
                        map.ScalarChannel = ObjMapChannel.Depth;
                        break;

                    default:
                        throw new InvalidDataException(string.Concat("A ", statement, " -imfchan option must specify a value in (r, g, b, m, l, z)."));
                    }

                    index++;
                    break;

                case "-mm":
                    if (values.Length - index < 3)
                    {
                        throw new InvalidDataException(string.Concat("A ", statement, " -mm option must specify a base and a gain."));
                    }

                    map.ModifierBase = float.Parse(values[index + 1], CultureInfo.InvariantCulture);
                    map.ModifierGain = float.Parse(values[index + 2], CultureInfo.InvariantCulture);

                    index += 2;
                    break;

                case "-o":
                    if (values.Length - index < 2)
                    {
                        throw new InvalidDataException(string.Concat("A ", statement, " -o option must specify at least 2 values."));
                    }

                    var offset = new ObjVector3();

                    offset.X = float.Parse(values[index + 1], CultureInfo.InvariantCulture);

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

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

                        index++;
                    }

                    index++;

                    map.Offset = offset;
                    break;

                case "-s":
                    if (values.Length - index < 2)
                    {
                        throw new InvalidDataException(string.Concat("A ", statement, " -s option must specify at least 2 values."));
                    }

                    var scale = new ObjVector3(1.0f, 1.0f, 1.0f);

                    scale.X = float.Parse(values[index + 1], CultureInfo.InvariantCulture);

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

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

                        index++;
                    }

                    index++;

                    map.Scale = scale;
                    break;

                case "-t":
                    if (values.Length - index < 2)
                    {
                        throw new InvalidDataException(string.Concat("A ", statement, " -t option must specify at least 2 values."));
                    }

                    var turbulence = new ObjVector3();

                    turbulence.X = float.Parse(values[index + 1], CultureInfo.InvariantCulture);

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

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

                        index++;
                    }

                    index++;

                    map.Turbulence = turbulence;
                    break;

                case "-texres":
                    if (values.Length - index < 2)
                    {
                        throw new InvalidDataException(string.Concat("A ", statement, " -texres option must specify a value."));
                    }

                    map.TextureResolution = int.Parse(values[index + 1], CultureInfo.InvariantCulture);

                    index++;
                    break;

                default:
                    if (!Path.HasExtension(values[index]))
                    {
                        throw new InvalidDataException("A filename must have an extension.");
                    }

                    map.FileName = values[index];
                    index++;

                    if (index != values.Length)
                    {
                        throw new InvalidDataException(string.Concat("A ", statement, " has too many values."));
                    }

                    break;
                }
            }

            return(map);
        }
Example #3
0
        private static void WriteMap(string statement, ObjMaterialMap map, StreamWriter stream)
        {
            // TODO: write tests

            stream.Write(statement);

            if (!map.IsHorizontalBlendingEnabled)
            {
                stream.Write(" -blenu off");
            }

            if (!map.IsVerticalBlendingEnabled)
            {
                stream.Write(" -blenv off");
            }

            if (map.BumpMultiplier != 0.0f)
            {
                stream.Write(" -bm ");
                stream.Write(map.BumpMultiplier.ToString("F6", CultureInfo.InvariantCulture));
            }

            if (map.Boost != 0.0f)
            {
                stream.Write(" -boost ");
                stream.Write(map.Boost.ToString("F6", CultureInfo.InvariantCulture));
            }

            if (map.IsColorCorrectionEnabled)
            {
                stream.Write(" -cc on");
            }

            if (map.IsClampingEnabled)
            {
                stream.Write(" -clamp on");
            }

            if (map.ScalarChannel != ObjMapChannel.Luminance)
            {
                stream.Write(" -imfchan ");

                switch (map.ScalarChannel)
                {
                case ObjMapChannel.Red:
                    stream.Write("r");
                    break;

                case ObjMapChannel.Green:
                    stream.Write("g");
                    break;

                case ObjMapChannel.Blue:
                    stream.Write("b");
                    break;

                case ObjMapChannel.Matte:
                    stream.Write("m");
                    break;

                case ObjMapChannel.Depth:
                    stream.Write("z");
                    break;

                default:
                    stream.Write("l");
                    break;
                }
            }

            if (map.ModifierBase != 0.0f || map.ModifierGain != 1.0f)
            {
                stream.Write(" -mm ");
                stream.Write(map.ModifierBase.ToString("F6", CultureInfo.InvariantCulture));
                stream.Write(' ');
                stream.Write(map.ModifierGain.ToString("F6", CultureInfo.InvariantCulture));
            }

            ObjVector3 offset = map.Offset;

            if (offset.X != 0.0f || offset.Y != 0.0f || offset.Z != 0.0f)
            {
                stream.Write(" -o ");
                stream.Write(offset.X.ToString("F6", CultureInfo.InvariantCulture));
                stream.Write(' ');
                stream.Write(offset.Y.ToString("F6", CultureInfo.InvariantCulture));
                stream.Write(' ');
                stream.Write(offset.Z.ToString("F6", CultureInfo.InvariantCulture));
            }

            ObjVector3 scale = map.Scale;

            if (scale.X != 1.0f || scale.Y != 1.0f || scale.Z != 1.0f)
            {
                stream.Write(" -s ");
                stream.Write(scale.X.ToString("F6", CultureInfo.InvariantCulture));
                stream.Write(' ');
                stream.Write(scale.Y.ToString("F6", CultureInfo.InvariantCulture));
                stream.Write(' ');
                stream.Write(scale.Z.ToString("F6", CultureInfo.InvariantCulture));
            }

            ObjVector3 turbulence = map.Turbulence;

            if (turbulence.X != 0.0f || turbulence.Y != 0.0f || turbulence.Z != 0.0f)
            {
                stream.Write(" -t ");
                stream.Write(turbulence.X.ToString("F6", CultureInfo.InvariantCulture));
                stream.Write(' ');
                stream.Write(turbulence.Y.ToString("F6", CultureInfo.InvariantCulture));
                stream.Write(' ');
                stream.Write(turbulence.Z.ToString("F6", CultureInfo.InvariantCulture));
            }

            if (map.TextureResolution != 0)
            {
                stream.Write(" -texres ");
                stream.Write(map.TextureResolution);
            }

            stream.Write(' ');
            stream.WriteLine(map.FileName);
        }
Example #4
0
        private static ObjMaterialColor ParseMaterialColor(string statement, string[] values)
        {
            if (values.Length < 2)
            {
                throw new InvalidDataException(string.Concat("A ", statement, " statement must specify a color."));
            }

            var color = new ObjMaterialColor();

            int index = 1;

            switch (values[1].ToLowerInvariant())
            {
            case "spectral":
                index++;

                if (values.Length - index < 1)
                {
                    throw new InvalidDataException(string.Concat("A ", statement, " spectral statement must specify a file name."));
                }

                if (!Path.HasExtension(values[index]))
                {
                    throw new InvalidDataException("A filename must have an extension.");
                }

                color.SpectralFileName = values[index];
                index++;

                if (values.Length > index)
                {
                    color.SpectralFactor = float.Parse(values[index], CultureInfo.InvariantCulture);
                    index++;
                }

                break;

            case "xyz":
                index++;

                if (values.Length - index < 1)
                {
                    throw new InvalidDataException(string.Concat("A ", statement, " xyz statement must specify a color."));
                }

                color.UseXYZColorSpace = true;

                var xyz = new ObjVector3();

                xyz.X = float.Parse(values[index], CultureInfo.InvariantCulture);
                index++;

                if (values.Length > index)
                {
                    if (values.Length - index < 2)
                    {
                        throw new InvalidDataException(string.Concat("A ", statement, " xyz statement must specify a XYZ color."));
                    }

                    xyz.Y  = float.Parse(values[index], CultureInfo.InvariantCulture);
                    xyz.Z  = float.Parse(values[index + 1], CultureInfo.InvariantCulture);
                    index += 2;
                }
                else
                {
                    xyz.Y = xyz.X;
                    xyz.Z = xyz.X;
                }

                color.Color = xyz;
                break;

            default:
                var rgb = new ObjVector3();

                rgb.X = float.Parse(values[index], CultureInfo.InvariantCulture);
                index++;

                if (values.Length > index)
                {
                    if (values.Length - index < 2)
                    {
                        throw new InvalidDataException(string.Concat("A ", statement, " statement must specify a RGB color."));
                    }

                    rgb.Y  = float.Parse(values[index], CultureInfo.InvariantCulture);
                    rgb.Z  = float.Parse(values[index + 1], CultureInfo.InvariantCulture);
                    index += 2;
                }
                else
                {
                    rgb.Y = rgb.X;
                    rgb.Z = rgb.X;
                }

                color.Color = rgb;
                break;
            }

            if (index != values.Length)
            {
                throw new InvalidDataException(string.Concat("A ", statement, " statement has too many values."));
            }

            return(color);
        }