コード例 #1
0
        private Face ReadFace(string line, UniqueNumberGenerator generator)
        {
            const NumberStyles ns = NumberStyles.Float;

            var parts = line.Split(' ').Where(x => !String.IsNullOrWhiteSpace(x)).ToList();

            Assert(parts[0] == "(");
            Assert(parts[4] == ")");
            Assert(parts[5] == "(");
            Assert(parts[9] == ")");
            Assert(parts[10] == "(");
            Assert(parts[14] == ")");

            var face = new Face(generator.Next("Face"))
            {
                Plane = new Plane(
                    NumericsExtensions.Parse(parts[1], parts[2], parts[3], ns, CultureInfo.InvariantCulture),
                    NumericsExtensions.Parse(parts[6], parts[7], parts[8], ns, CultureInfo.InvariantCulture),
                    NumericsExtensions.Parse(parts[11], parts[12], parts[13], ns, CultureInfo.InvariantCulture)
                    ),
                Texture = { Name = parts[15] }
            };

            // Cater for older-style map formats
            // TODO Quake 3: when the MAP face has 24 parts, the last three parts are: content_flags, surface_flags, value
            if (parts.Count == 21 || parts.Count == 24)
            {
                QuakeEdAlignTextureToWorld(face);

                var xshift = float.Parse(parts[16], ns, CultureInfo.InvariantCulture);
                var yshift = float.Parse(parts[17], ns, CultureInfo.InvariantCulture);
                var rotate = float.Parse(parts[18], ns, CultureInfo.InvariantCulture);
                var xscale = float.Parse(parts[19], ns, CultureInfo.InvariantCulture);
                var yscale = float.Parse(parts[20], ns, CultureInfo.InvariantCulture);

                face.Texture.Rotation = -rotate;
                face.Texture.Rotation = rotate;
                face.Texture.XScale   = xscale;
                face.Texture.YScale   = yscale;
                face.Texture.XShift   = xshift;
                face.Texture.YShift   = yshift;
            }
            else
            {
                Assert(parts[16] == "[");
                Assert(parts[21] == "]");
                Assert(parts[22] == "[");
                Assert(parts[27] == "]");

                face.Texture.UAxis    = NumericsExtensions.Parse(parts[17], parts[18], parts[19], ns, CultureInfo.InvariantCulture);
                face.Texture.XShift   = float.Parse(parts[20], ns, CultureInfo.InvariantCulture);
                face.Texture.VAxis    = NumericsExtensions.Parse(parts[23], parts[24], parts[25], ns, CultureInfo.InvariantCulture);
                face.Texture.YShift   = float.Parse(parts[26], ns, CultureInfo.InvariantCulture);
                face.Texture.Rotation = float.Parse(parts[28], ns, CultureInfo.InvariantCulture);
                face.Texture.XScale   = float.Parse(parts[29], ns, CultureInfo.InvariantCulture);
                face.Texture.YScale   = float.Parse(parts[30], ns, CultureInfo.InvariantCulture);
            }

            return(face);
        }
コード例 #2
0
        private static void ReadProperty(Entity ent, string line)
        {
            // Quake id1 map sources use tabs between keys and values
            var split = line.Split(new char[] { ' ', '\t' });
            var key   = split[0].Trim('"');

            var val = String.Join(" ", split.Skip(1)).Trim('"');

            if (key == "classname")
            {
                ent.EntityData.Name = val;
            }
            else if (key == "spawnflags")
            {
                ent.EntityData.Flags = int.Parse(val);
            }
            else if (key == "origin")
            {
                var osp = val.Split(' ');
                ent.Origin = NumericsExtensions.Parse(osp[0], osp[1], osp[2], NumberStyles.Float, CultureInfo.InvariantCulture);
            }
            else if (!ExcludedKeys.Contains(key.ToLower()))
            {
                ent.EntityData.Set(key, val);
            }
        }
コード例 #3
0
        public Vector3?GetVector3(int index)
        {
            var first = index * 3;

            return(Values.Count < first + 3
                ? (Vector3?)null
                : NumericsExtensions.Parse(Values[first], Values[first + 1], Values[first + 2], NumberStyles.Float, CultureInfo.InvariantCulture));
        }
コード例 #4
0
 public void TestParse()
 {
     Assert.AreEqual(
         NumericsExtensions.Parse("1", "2", "3", NumberStyles.Float, CultureInfo.InvariantCulture),
         new Vector3(1, 2, 3)
         );
     Assert.AreEqual(
         NumericsExtensions.Parse("1,01", "2,02", "3,03", NumberStyles.Float, CultureInfo.GetCultureInfo("es-ES")),
         new Vector3(1.01f, 2.02f, 3.03f)
         );
 }
コード例 #5
0
        public void MatrixTest()
        {
            var t        = new Vector3(1, 2, 3);
            var orgAxis  = Vector3.Normalize(new Vector3(1, 2, 3));
            var orgAngle = 90 * NumericsExtensions.TO_RAD;
            var r        = Quaternion.CreateFromAxisAngle(orgAxis, orgAngle);
            var s        = new Vector3(2, 3, 4);
            var m        = NumericsExtensions.FromTRS(t, r, s);

            var(tt, rr, ss) = m.Decompose();
            Assert.True(s.NearlyEqual(ss));
            Assert.True(r.NearlyEqual(rr));
            Assert.AreEqual(t, tt);
        }
コード例 #6
0
        public static Pointfile Parse(IEnumerable <string> lines)
        {
            var pf   = new Pointfile();
            var list = lines.ToList();

            if (!list.Any())
            {
                return(pf);
            }

            // Format detection: look at one line
            // .lin format: coordinate - coordinate
            // .pts format: coordinate
            var detect = list[0].Split(' ');
            var lin    = detect.Length == 7;
            var pts    = detect.Length == 3;

            if (!lin && !pts)
            {
                throw new Exception("Invalid pointfile format.");
            }

            Vector3?previous = null;

            foreach (var line in list)
            {
                var split = line.Split(' ');
                var point = NumericsExtensions.Parse(split[0], split[1], split[2], NumberStyles.Float, CultureInfo.InvariantCulture);
                if (lin)
                {
                    var point2 = NumericsExtensions.Parse(split[4], split[5], split[6], NumberStyles.Float, CultureInfo.InvariantCulture);
                    pf.Lines.Add(new Line(point2, point));
                }
                else // pts
                {
                    if (previous.HasValue)
                    {
                        pf.Lines.Add(new Line(previous.Value, point));
                    }
                    previous = point;
                }
            }

            return(pf);
        }
コード例 #7
0
 public VmfSide(SerialisedObject obj)
 {
     ID   = obj.Get("ID", 0L);
     Face = new Face
     {
         TextureName     = obj.Get("material", ""),
         Rotation        = obj.Get("rotation", 0f),
         LightmapScale   = obj.Get("lightmapscale", 0),
         SmoothingGroups = obj.Get("smoothing_groups", "")
     };
     if (Util.ParseFloatArray(obj.Get("plane", ""), new[] { ' ', '(', ')' }, 9, out var pl))
     {
         Face.Plane = NumericsExtensions.PlaneFromVertices(
             new Vector3(pl[0], pl[1], pl[2]).Round(),
             new Vector3(pl[3], pl[4], pl[5]).Round(),
             new Vector3(pl[6], pl[7], pl[8]).Round()
             );
     }
     else
     {
         Face.Plane = new Plane(Vector3.UnitZ, 0);
     }
     if (Util.ParseFloatArray(obj.Get("uaxis", ""), new[] { ' ', '[', ']' }, 5, out float[] ua))
コード例 #8
0
        static void WriteEntity(Entity entity, BinaryWriter bw)
        {
            bw.WriteCString("CMapEntity", MaxVariableStringLength);
            WriteMapBase(entity, bw);
            WriteEntityData(entity, bw);
            bw.Write(new byte[2]); // Unused

            Vector3 origin = new Vector3();

            if (entity.Properties.ContainsKey("origin"))
            {
                string o = entity.Properties["origin"];
                if (!string.IsNullOrWhiteSpace(o))
                {
                    string[] parts = o.Split(' ');
                    if (parts.Length == 3)
                    {
                        NumericsExtensions.TryParse(parts[0], parts[1], parts[2], NumberStyles.Float, CultureInfo.InvariantCulture, out origin);
                    }
                }
            }
            bw.WriteVector3(origin);
            bw.Write(new byte[4]); // Unused
        }
コード例 #9
0
        private void Read(Map map, StreamReader reader)
        {
            const NumberStyles ns = NumberStyles.Float;

            var points       = new List <Vector3>();
            var faces        = new List <ObjFace>();
            var currentGroup = "default";
            var scale        = 100f;

            string line;

            while ((line = reader.ReadLine()) != null)
            {
                if (line.StartsWith("# Scale: "))
                {
                    var num = line.Substring(9);
                    if (float.TryParse(num, NumberStyles.Float, CultureInfo.InvariantCulture, out var s))
                    {
                        scale = s;
                    }
                }

                line = CleanLine(line);
                SplitLine(line, out var keyword, out var values);
                if (String.IsNullOrWhiteSpace(keyword))
                {
                    continue;
                }

                var vals = (values ?? "").Split(' ').Where(x => !String.IsNullOrWhiteSpace(x)).ToArray();
                switch (keyword.ToLower())
                {
                // Things I care about
                case "v":     // geometric vertices
                    var vec = NumericsExtensions.Parse(vals[0], vals[1], vals[2], ns, CultureInfo.InvariantCulture);
                    points.Add(vec * scale);
                    break;

                case "f":     // face
                    faces.Add(new ObjFace(currentGroup, vals.Select(x => ParseFaceIndex(points, x))));
                    break;

                case "g":     // group name
                    currentGroup = (values ?? "").Trim();
                    break;

                    // Things I don't care about
                    #region Not Implemented

                // Vertex data
                // "v"
                case "vt":     // texture vertices
                    break;

                case "vn":     // vertex normals
                    break;

                case "vp":     // parameter space vertices
                case "cstype": // rational or non-rational forms of curve or surface type: basis matrix, Bezier, B-spline, Cardinal, Taylor
                case "degree": // degree
                case "bmat":   // basis matrix
                case "step":   // step size
                    // not supported
                    break;

                // Elements
                // "f"
                case "p":     // point
                case "l":     // line
                case "curv":  // curve
                case "curv2": // 2D curve
                case "surf":  // surface
                    // not supported
                    break;

                // Free-form curve/surface body statements
                case "parm":    // parameter name
                case "trim":    // outer trimming loop (trim)
                case "hole":    // inner trimming loop (hole)
                case "scrv":    // special curve (scrv)
                case "sp":      // special point (sp)
                case "end":     // end statement (end)
                    // not supported
                    break;

                // Connectivity between free-form surfaces
                case "con":     // connect
                    // not supported
                    break;

                // Grouping
                // "g"
                case "s":     // smoothing group
                    break;

                case "mg":     // merging group
                    break;

                case "o":     // object name
                    // not supported
                    break;

                // Display/render attributes
                case "mtllib":     // material library
                case "usemtl":     // material name
                case "usemap":     // texture map name
                case "bevel":      // bevel interpolation
                case "c_interp":   // color interpolation
                case "d_interp":   // dissolve interpolation
                case "lod":        // level of detail
                case "shadow_obj": // shadow casting
                case "trace_obj":  // ray tracing
                case "ctech":      // curve approximation technique
                case "stech":      // surface approximation technique
                    // not relevant
                    break;

                    #endregion
                }
            }

            var solids = new List <Solid>();

            // Try and see if we have a valid solid per-group
            foreach (var g in faces.GroupBy(x => x.Group))
            {
                solids.AddRange(CreateSolids(map, points, g));
            }

            foreach (var solid in solids)
            {
                foreach (var face in solid.Faces)
                {
                    face.Texture.AlignToNormal(face.Plane.Normal);
                }

                solid.Hierarchy.Parent = map.Root;
            }

            map.Root.DescendantsChanged();
        }
コード例 #10
0
        static Face ReadFace(string line)
        {
            const NumberStyles ns = NumberStyles.Float;

            List <string> parts = line.Split(' ').ToList();

            Util.Assert(parts[0] == "(");
            Util.Assert(parts[4] == ")");
            Util.Assert(parts[5] == "(");
            Util.Assert(parts[9] == ")");
            Util.Assert(parts[10] == "(");
            Util.Assert(parts[14] == ")");

            Vector3 a = NumericsExtensions.Parse(parts[1], parts[2], parts[3], ns, CultureInfo.InvariantCulture);
            Vector3 b = NumericsExtensions.Parse(parts[6], parts[7], parts[8], ns, CultureInfo.InvariantCulture);
            Vector3 c = NumericsExtensions.Parse(parts[11], parts[12], parts[13], ns, CultureInfo.InvariantCulture);

            Vector3 ab = b - a;
            Vector3 ac = c - a;

            Vector3 normal = ac.Cross(ab).Normalise();
            float   d      = normal.Dot(a);

            Face face = new Face()
            {
                Plane       = new Plane(normal, d),
                TextureName = parts[15]
            };

            // idTech2, idTech3
            if (parts.Count == 21 || parts.Count == 24)
            {
                Vector3 direction = ClosestAxisToNormal(face.Plane);
                face.UAxis = direction == Vector3.UnitX ? Vector3.UnitY : Vector3.UnitX;
                face.VAxis = direction == Vector3.UnitZ ? -Vector3.UnitY : -Vector3.UnitZ;

                float xshift = float.Parse(parts[16], ns, CultureInfo.InvariantCulture);
                float yshift = float.Parse(parts[17], ns, CultureInfo.InvariantCulture);
                float rotate = float.Parse(parts[18], ns, CultureInfo.InvariantCulture);
                float xscale = float.Parse(parts[19], ns, CultureInfo.InvariantCulture);
                float yscale = float.Parse(parts[20], ns, CultureInfo.InvariantCulture);

                face.Rotation = rotate;
                face.XScale   = xscale;
                face.YScale   = yscale;
                face.XShift   = xshift;
                face.YShift   = yshift;

                // idTech3
                if (parts.Count == 24)
                {
                    face.ContentFlags = int.Parse(parts[18], CultureInfo.InvariantCulture);
                    face.SurfaceFlags = int.Parse(parts[19], CultureInfo.InvariantCulture);
                    face.Value        = float.Parse(parts[20], ns, CultureInfo.InvariantCulture);
                }
            }
            // Worldcraft
            else if (parts.Count == 31)
            {
                Util.Assert(parts[16] == "[");
                Util.Assert(parts[21] == "]");
                Util.Assert(parts[22] == "[");
                Util.Assert(parts[27] == "]");

                face.UAxis    = NumericsExtensions.Parse(parts[17], parts[18], parts[19], ns, CultureInfo.InvariantCulture);
                face.XShift   = float.Parse(parts[20], ns, CultureInfo.InvariantCulture);
                face.VAxis    = NumericsExtensions.Parse(parts[23], parts[24], parts[25], ns, CultureInfo.InvariantCulture);
                face.YShift   = float.Parse(parts[26], ns, CultureInfo.InvariantCulture);
                face.Rotation = float.Parse(parts[28], ns, CultureInfo.InvariantCulture);
                face.XScale   = float.Parse(parts[29], ns, CultureInfo.InvariantCulture);
                face.YScale   = float.Parse(parts[30], ns, CultureInfo.InvariantCulture);
            }
            else
            {
                Util.Assert(false, $"Unknown number of tokens ({parts.Count}) in face definition.");
            }

            return(face);
        }