示例#1
0
        protected override DataStructures.MapObjects.Map GetFromStream(Stream stream)
        {
            var map = new DataStructures.MapObjects.Map();
            var br = new BinaryReader(stream);

            // Only RMF version 2.2 is supported for the moment.
            var version = Math.Round(br.ReadSingle(), 1);
            if (Math.Abs(version - 2.2) > 0.01)
            {
                throw new ProviderException("Incorrect RMF version number. Expected 2.2, got " + version + ".");
            }
            map.Version = (decimal) version;

            // RMF header test
            var header = br.ReadFixedLengthString(Encoding.UTF8, 3);
            if (header != "RMF")
            {
                throw new ProviderException("Incorrect RMF header. Expected 'RMF', got '" + header + "'.");
            }

            // Visgroups
            var visgroups = ReadVisgroups(br);
            map.Visgroups.AddRange(visgroups);

            // Map Objects
            map.IDGenerator.Reset(); // So the world will be ID = 1
            var worldspawn = ReadWorldSpawn(br, map.Visgroups, map.IDGenerator);
            map.WorldSpawn = worldspawn;

            // DOCINFO string check
            var docinfo = br.ReadFixedLengthString(Encoding.UTF8, 8);
            if (docinfo != "DOCINFO")
            {
                throw new ProviderException("Incorrect RMF format. Expected 'DOCINFO', got '" + docinfo + "'.");
            }

            // Cameras
            br.ReadSingle(); // Appears to be a version number for camera data. Unused.
            var activeCamera = br.ReadInt32();
            var cameras = ReadCameras(br);
            map.Cameras.AddRange(cameras);
            if (activeCamera >= 0 && activeCamera < map.Cameras.Count)
            {
                map.ActiveCamera = map.Cameras[activeCamera];
            }

            return map;
        }
示例#2
0
 /// <summary>
 /// Reads a map from a stream in MAP format.
 /// </summary>
 /// <param name="stream">The stream to read from</param>
 /// <returns>The parsed map</returns>
 protected override DataStructures.MapObjects.Map GetFromStream(Stream stream)
 {
     using (var reader = new StreamReader(stream))
     {
         var map = new DataStructures.MapObjects.Map();
         var allentities = ReadAllEntities(reader, map.IDGenerator);
         var worldspawn = allentities.FirstOrDefault(x => x.EntityData.Name == "worldspawn")
                          ?? new Entity(0) {EntityData = {Name = "worldspawn"}};
         allentities.Remove(worldspawn);
         map.WorldSpawn.EntityData = worldspawn.EntityData;
         allentities.ForEach(x => x.SetParent(map.WorldSpawn, false));
         foreach (var obj in worldspawn.GetChildren().ToArray())
         {
             obj.SetParent(map.WorldSpawn, false);
         }
         map.WorldSpawn.UpdateBoundingBox(false);
         return map;
     }
 }
示例#3
0
        private static GenericStructure WriteWorld(DataStructures.MapObjects.Map map, IEnumerable <Solid> solids, IEnumerable <Group> groups)
        {
            var world = map.WorldSpawn;
            var ret   = new GenericStructure("world");

            ret["id"]         = world.ID.ToString(CultureInfo.InvariantCulture);
            ret["classname"]  = "worldspawn";
            ret["mapversion"] = map.Version.ToString(CultureInfo.InvariantCulture);
            WriteEntityData(ret, world.EntityData);

            foreach (var solid in solids.OrderBy(x => x.ID))
            {
                ret.Children.Add(WriteSolid(solid));
            }

            foreach (var group in groups.OrderBy(x => x.ID))
            {
                ret.Children.Add(WriteGroup(group));
            }

            return(ret);
        }
示例#4
0
 /// <summary>
 /// Reads a map from a stream in MAP format.
 /// </summary>
 /// <param name="stream">The stream to read from</param>
 /// <returns>The parsed map</returns>
 protected override DataStructures.MapObjects.Map GetFromStream(Stream stream, string fgd = null)
 {
     using (var reader = new StreamReader(stream))
     {
         var map         = new DataStructures.MapObjects.Map();
         var allentities = ReadAllEntities(reader, map.IDGenerator);
         var worldspawn  = allentities.FirstOrDefault(x => x.EntityData.Name == "worldspawn")
                           ?? new Entity(0)
         {
             EntityData = { Name = "worldspawn" }
         };
         allentities.Remove(worldspawn);
         map.WorldSpawn.EntityData = worldspawn.EntityData;
         allentities.ForEach(x => x.SetParent(map.WorldSpawn, false));
         foreach (var obj in worldspawn.GetChildren().ToArray())
         {
             obj.SetParent(map.WorldSpawn, false);
         }
         map.WorldSpawn.UpdateBoundingBox(false);
         return(map);
     }
 }
示例#5
0
        protected override DataStructures.MapObjects.Map GetFromStream(Stream stream)
        {
            using (var reader = new StreamReader(stream))
            {
                var map = new DataStructures.MapObjects.Map();
                Read(map, reader);

                /*
                 * var allentities = ReadAllEntities(reader, map.IDGenerator);
                 * var worldspawn = allentities.FirstOrDefault(x => x.EntityData.Name == "worldspawn")
                 *               ?? new Entity(0) { EntityData = { Name = "worldspawn" } };
                 * allentities.Remove(worldspawn);
                 * map.WorldSpawn.EntityData = worldspawn.EntityData;
                 * allentities.ForEach(x => x.SetParent(map.WorldSpawn));
                 * foreach (var obj in worldspawn.Children.ToArray())
                 * {
                 *  obj.SetParent(map.WorldSpawn);
                 * }
                 * map.WorldSpawn.UpdateBoundingBox(false);
                 */
                return(map);
            }
        }
示例#6
0
        protected override DataStructures.MapObjects.Map GetFromStream(Stream stream, string fgd = null)
        {
            using (var reader = new StreamReader(stream))
            {
                var parent = new GenericStructure("Root");
                parent.Children.AddRange(GenericStructure.Parse(reader));
                // Sections from a Hammer map:
                // - world
                // - entity
                // - visgroups
                // - cordon
                // Not done yet
                // - versioninfo
                // - viewsettings
                // - cameras

                var map = new DataStructures.MapObjects.Map();

                var world        = parent.GetChildren("world").FirstOrDefault();
                var entities     = parent.GetChildren("entity");
                var visgroups    = parent.GetChildren("visgroups").SelectMany(x => x.GetChildren("visgroup"));
                var cameras      = parent.GetChildren("cameras").FirstOrDefault();
                var cordon       = parent.GetChildren("cordon").FirstOrDefault();
                var viewsettings = parent.GetChildren("viewsettings").FirstOrDefault();

                foreach (var visgroup in visgroups)
                {
                    var vg = ReadVisgroup(visgroup);
                    if (vg.ID < 0 && vg.Name == "Auto")
                    {
                        continue;
                    }
                    map.Visgroups.Add(vg);
                }

                if (world != null)
                {
                    map.WorldSpawn = ReadWorld(world, map.IDGenerator);
                }
                foreach (var entity in entities)
                {
                    var ent       = ReadEntity(entity, map.IDGenerator);
                    var groupid   = entity.Children.Where(x => x.Name == "editor").Select(x => x.PropertyInteger("groupid")).FirstOrDefault();
                    var entParent = groupid > 0 ? map.WorldSpawn.Find(x => x.ID == groupid && x is Group).FirstOrDefault() ?? map.WorldSpawn : map.WorldSpawn;
                    ent.SetParent(entParent);
                }

                var activeCamera = 0;
                if (cameras != null)
                {
                    activeCamera = cameras.PropertyInteger("activecamera");
                    foreach (var cam in cameras.GetChildren("camera"))
                    {
                        var pos  = cam.PropertyCoordinate("position");
                        var look = cam.PropertyCoordinate("look");
                        if (pos != null && look != null)
                        {
                            map.Cameras.Add(new Camera {
                                EyePosition = pos, LookPosition = look
                            });
                        }
                    }
                }
                if (!map.Cameras.Any())
                {
                    map.Cameras.Add(new Camera {
                        EyePosition = Coordinate.Zero, LookPosition = Coordinate.UnitY
                    });
                }
                if (activeCamera < 0 || activeCamera >= map.Cameras.Count)
                {
                    activeCamera = 0;
                }
                map.ActiveCamera = map.Cameras[activeCamera];

                if (cordon != null)
                {
                    var start = cordon.PropertyCoordinate("mins", map.CordonBounds.Start);
                    var end   = cordon.PropertyCoordinate("maxs", map.CordonBounds.End);
                    map.CordonBounds = new Box(start, end);
                    map.Cordon       = cordon.PropertyBoolean("active", map.Cordon);
                }

                if (viewsettings != null)
                {
                    map.SnapToGrid         = viewsettings.PropertyBoolean("bSnapToGrid", map.SnapToGrid);
                    map.Show2DGrid         = viewsettings.PropertyBoolean("bShowGrid", map.Show2DGrid);
                    map.Show3DGrid         = viewsettings.PropertyBoolean("bShow3DGrid", map.Show3DGrid);
                    map.GridSpacing        = viewsettings.PropertyDecimal("nGridSpacing", map.GridSpacing);
                    map.IgnoreGrouping     = viewsettings.PropertyBoolean("bIgnoreGrouping", map.IgnoreGrouping);
                    map.HideFaceMask       = viewsettings.PropertyBoolean("bHideFaceMask", map.HideFaceMask);
                    map.HideNullTextures   = viewsettings.PropertyBoolean("bHideNullTextures", map.HideNullTextures);
                    map.TextureLock        = viewsettings.PropertyBoolean("bTextureLock", map.TextureLock);
                    map.TextureScalingLock = viewsettings.PropertyBoolean("bTextureScalingLock", map.TextureScalingLock);
                }

                return(map);
            }
        }
示例#7
0
        protected void ReadMemblockMesh(BinaryReader br, DataStructures.MapObjects.Map map, List <Face> faces = null)
        {
            UInt32 memblockSize = br.ReadUInt32();
            long   startPos     = br.BaseStream.Position;

            UInt32 dwFVF     = br.ReadUInt32();
            UInt32 dwFVFSize = br.ReadUInt32();
            UInt32 dwVertMax = br.ReadUInt32();

            List <CoordinateF> vertexPositions = new List <CoordinateF>();
            List <CoordinateF> vertexNormals   = new List <CoordinateF>();

            for (int i = 0; i < dwVertMax; i++)
            {
                float x = br.ReadSingle();
                float z = br.ReadSingle();
                float y = br.ReadSingle();
                vertexPositions.Add(new CoordinateF(x, y, z));
                float nx = br.ReadSingle();
                float nz = br.ReadSingle();
                float ny = br.ReadSingle();
                vertexNormals.Add(new CoordinateF(nx, ny, nz).Normalise());
                for (int j = 24; j < dwFVFSize; j += 4)
                {
                    br.BaseStream.Position += 4;
                }
            }

            if (faces != null)
            {
                foreach (var normal in vertexNormals.Distinct(new NormalEq()))
                {
                    if (normal.LengthSquared() < 0.01f)
                    {
                        continue;
                    }
                    Face newFace = new Face(map.IDGenerator.GetNextFaceID());
                    for (int i = 0; i < vertexPositions.Count; i++)
                    {
                        if (vertexNormals[i].Dot(normal) < 0.999f)
                        {
                            continue;
                        }
                        if (newFace.Vertices.Any(v => (new CoordinateF(v.Location) - vertexPositions[i]).LengthSquared() < 0.001f))
                        {
                            continue;
                        }
                        newFace.Vertices.Add(new Vertex(new Coordinate(vertexPositions[i]), newFace));
                    }

                    newFace.Plane = new Plane(new Coordinate(normal), newFace.Vertices[0].Location);

                    Vertex center = newFace.Vertices[0];
                    newFace.Vertices.RemoveAt(0);

                    newFace.Vertices.Sort((v1, v2) => {
                        float dot = normal.Dot(new CoordinateF((v1.Location - center.Location).Cross(v2.Location - center.Location)));
                        if (dot < 0.0f)
                        {
                            return(-1);
                        }
                        else if (dot > 0.0f)
                        {
                            return(1);
                        }
                        return(0);
                    });

                    newFace.Vertices.Insert(0, center);

                    newFace.UpdateBoundingBox();

                    faces.Add(newFace);
                }
            }

            br.BaseStream.Position = startPos + (long)memblockSize;
        }
示例#8
0
 protected virtual void SaveToFile(string filename, DataStructures.MapObjects.Map map, DataStructures.GameData.GameData gameData, TextureCollection textureCollection)
 {
     using (var strm = new FileStream(filename, FileMode.Create, FileAccess.Write)) {
         SaveToStream(strm, map, gameData, textureCollection);
     }
 }
示例#9
0
        protected override DataStructures.MapObjects.Map GetFromStream(Stream stream)
        {
            var map = new DataStructures.MapObjects.Map();

            map.CordonBounds = new Box(Coordinate.One * -16384, Coordinate.One * 16384);
            BinaryReader br = new BinaryReader(stream);

            //header
            UInt16 mapVersion   = br.ReadUInt16();
            byte   mapFlags     = br.ReadByte();
            Int32  nameCount    = br.ReadInt32();
            Int32  nameOffset   = br.ReadInt32();
            Int32  objectCount  = br.ReadInt32();
            Int32  objectOffset = br.ReadInt32();

            //get names, needed to understand the objects
            List <string> names = new List <string>();

            br.BaseStream.Seek(nameOffset, SeekOrigin.Begin);
            for (int i = 0; i < nameCount; i++)
            {
                string name = br.ReadNullTerminatedString();
                names.Add(name);
            }

            //now we can parse the object table
            List <string> materials = new List <string>();
            List <Tuple <int, string> > meshReferences = new List <Tuple <int, string> >();

            br.BaseStream.Seek(objectOffset, SeekOrigin.Begin);
            long objectStartPos = br.BaseStream.Position;

            for (int i = 0; i < objectCount; i++)
            {
                int index = br.ReadInt32() - 1;
                int size  = br.ReadInt32();
                if (index < 0 || index >= names.Count)
                {
                    throw new Exception(i.ToString() + " " + index.ToString());
                }
                string name = names[index];

                if (name == "meshreference")
                {
                    byte flags = br.ReadByte();

                    Int32 groupNameInd  = br.ReadInt32() - 1;
                    Int32 objectNameInd = br.ReadInt32() - 1;

                    byte limbCount = br.ReadByte();

                    meshReferences.Add(new Tuple <int, string>(i, names[objectNameInd]));
                }
                else if (name == "material")
                {
                    byte   materialFlags      = br.ReadByte();
                    Int32  groupIndex         = br.ReadInt32();
                    string objectName         = names[br.ReadInt32() - 1];
                    Int32  extensionNameIndex = -1;
                    if ((materialFlags & 2) != 0)
                    {
                        extensionNameIndex = br.ReadInt32(); //TODO: what the heck is this
                    }
                    materials.Add(objectName);
                }
                else
                {
                    br.BaseStream.Seek(size, SeekOrigin.Current);
                }
            }
            br.BaseStream.Position = objectStartPos;
            for (int i = 0; i < objectCount; i++)
            {
                int index = br.ReadInt32() - 1;
                int size  = br.ReadInt32();
                if (index < 0 || index >= names.Count)
                {
                    throw new Exception(i.ToString() + " " + index.ToString());
                }
                string name = names[index];
                if (name == "mesh")
                {
                    Property newProperty;

                    long startPos = br.BaseStream.Position;

                    byte flags = br.ReadByte();

                    Entity entity = new Entity(map.IDGenerator.GetNextObjectID());
                    entity.ClassName       = "model";
                    entity.EntityData.Name = "model";
                    entity.Colour          = Colour.GetDefaultEntityColour();

                    Int32 keyCount = br.ReadInt32();
                    for (int j = 0; j < keyCount; j++)
                    {
                        Int32 keyNameInd  = br.ReadInt32() - 1;
                        Int32 keyValueInd = br.ReadInt32() - 1;
                        if (names[keyNameInd] == "classname")
                        {
                            //entity.ClassName = names[keyValueInd];
                            //entity.EntityData.Name = names[keyValueInd];
                        }
                        else
                        {
                            newProperty       = new Property();
                            newProperty.Key   = names[keyNameInd];
                            newProperty.Value = names[keyValueInd];

                            if (newProperty.Key == "file")
                            {
                                newProperty.Value = System.IO.Path.GetFileNameWithoutExtension(newProperty.Value);
                            }

                            entity.EntityData.Properties.Add(newProperty);
                        }
                    }
                    Int32 group    = br.ReadInt32();
                    Int32 visgroup = br.ReadInt32();

                    byte red = br.ReadByte(); byte green = br.ReadByte(); byte blue = br.ReadByte();

                    Int32 meshRefIndex = br.ReadInt32() - 1;

                    float x = br.ReadSingle();
                    float z = br.ReadSingle();
                    float y = br.ReadSingle();
                    if (entity != null)
                    {
                        entity.Origin = new Coordinate((decimal)x, (decimal)y, (decimal)z);
                    }

                    if (entity.EntityData.GetPropertyValue("file") == null)
                    {
                        newProperty       = new Property();
                        newProperty.Key   = "file";
                        newProperty.Value = meshReferences.Find(q => q.Item1 == meshRefIndex).Item2;

                        entity.EntityData.Properties.Add(newProperty);
                    }

                    float pitch = br.ReadSingle();
                    float yaw   = br.ReadSingle();
                    float roll  = br.ReadSingle();
                    newProperty       = new Property();
                    newProperty.Key   = "angles";
                    newProperty.Value = pitch.ToString(CultureInfo.InvariantCulture) + " " + yaw.ToString(CultureInfo.InvariantCulture) + " " + roll.ToString(CultureInfo.InvariantCulture);

                    entity.EntityData.Properties.Add(newProperty);

                    float xScale = 1.0f;
                    float yScale = 1.0f;
                    float zScale = 1.0f;

                    if ((flags & 1) == 0)
                    {
                        xScale = br.ReadSingle();
                        yScale = br.ReadSingle();
                        zScale = br.ReadSingle();
                    }

                    newProperty       = new Property();
                    newProperty.Key   = "scale";
                    newProperty.Value = xScale.ToString(CultureInfo.InvariantCulture) + " " + yScale.ToString(CultureInfo.InvariantCulture) + " " + zScale.ToString(CultureInfo.InvariantCulture);

                    entity.EntityData.Properties.Add(newProperty);

                    br.BaseStream.Position += size - (br.BaseStream.Position - startPos);

                    if (entity != null)
                    {
                        entity.UpdateBoundingBox();
                        entity.SetParent(map.WorldSpawn);
                    }
                }
                else if (name == "entity")
                {
                    byte  flags = br.ReadByte();
                    float x     = br.ReadSingle();
                    float z     = br.ReadSingle();
                    float y     = br.ReadSingle();

                    Entity entity = new Entity(map.IDGenerator.GetNextObjectID());
                    entity.Colour = Colour.GetDefaultEntityColour();
                    entity.Origin = new Coordinate((decimal)x, (decimal)y, (decimal)z);

                    Int32 keyCount = br.ReadInt32();
                    for (int j = 0; j < keyCount; j++)
                    {
                        Int32 keyNameInd  = br.ReadInt32() - 1;
                        Int32 keyValueInd = br.ReadInt32() - 1;
                        if (names[keyNameInd] == "classname")
                        {
                            entity.ClassName       = names[keyValueInd];
                            entity.EntityData.Name = names[keyValueInd];
                        }
                        else
                        {
                            Property newProperty = new Property();
                            newProperty.Key   = names[keyNameInd];
                            newProperty.Value = names[keyValueInd];
                            entity.EntityData.Properties.Add(newProperty);
                        }
                    }
                    Int32 group    = br.ReadInt32();
                    Int32 visgroup = br.ReadInt32();

                    entity.UpdateBoundingBox();
                    entity.SetParent(map.WorldSpawn);
                }
                else if (name == "brush")
                {
                    bool invisibleCollision = false;

                    byte  brushFlags = br.ReadByte(); //TODO: ???
                    Int32 keys       = br.ReadInt32();
                    for (int j = 0; j < keys; j++)
                    {
                        Int32  keyNameInd  = br.ReadInt32();
                        Int32  keyValueInd = br.ReadInt32();
                        string keyName     = names[keyNameInd - 1];
                        if (keyName.Equals("classname", StringComparison.InvariantCultureIgnoreCase))
                        {
                            string keyValue = names[keyValueInd - 1];
                            if (keyValue.Equals("field_hit", StringComparison.InvariantCultureIgnoreCase))
                            {
                                invisibleCollision = true;
                            }
                        }
                    }
                    Int32 groupIndex    = br.ReadInt32();
                    Int32 visgroupIndex = br.ReadInt32();

                    byte red = br.ReadByte(); byte green = br.ReadByte(); byte blue = br.ReadByte();

                    List <Coordinate> vertices = new List <Coordinate>();
                    byte vertexCount           = br.ReadByte();
                    for (int j = 0; j < vertexCount; j++)
                    {
                        decimal x = (decimal)br.ReadSingle(); decimal z = (decimal)br.ReadSingle(); decimal y = (decimal)br.ReadSingle();
                        vertices.Add(new Coordinate(x, y, z));
                    }
                    List <Face> faces     = new List <Face>();
                    byte        faceCount = br.ReadByte();
                    for (int j = 0; j < faceCount; j++)
                    {
                        byte faceFlags = br.ReadByte();

                        //TODO: maybe we need these unused bits for something idk
                        decimal planeEq0 = (decimal)br.ReadSingle(); decimal planeEq1 = (decimal)br.ReadSingle(); decimal planeEq2 = (decimal)br.ReadSingle(); decimal planeEq3 = (decimal)br.ReadSingle();

                        decimal texPosX = (decimal)br.ReadSingle(); decimal texPosY = (decimal)br.ReadSingle();
                        decimal texScaleX = (decimal)br.ReadSingle(); decimal texScaleY = (decimal)br.ReadSingle();
                        float   texRotX = br.ReadSingle(); float texRotY = br.ReadSingle();

                        decimal uTexPlane0 = (decimal)br.ReadSingle(); decimal uTexPlane1 = (decimal)br.ReadSingle(); decimal uTexPlane2 = (decimal)br.ReadSingle(); decimal uTexPlane3 = (decimal)br.ReadSingle();
                        decimal vTexPlane0 = (decimal)br.ReadSingle(); decimal vTexPlane1 = (decimal)br.ReadSingle(); decimal vTexPlane2 = (decimal)br.ReadSingle(); decimal vTexPlane3 = (decimal)br.ReadSingle();

                        float luxelSize = br.ReadSingle();

                        Int32 smoothGroupInd = br.ReadInt32();
                        Int32 materialInd    = br.ReadInt32() - 1;

                        Int32 lightmapInd = -1;
                        if ((faceFlags & 16) != 0)
                        {
                            lightmapInd = br.ReadInt32();
                        }

                        byte        indexCount  = br.ReadByte();
                        List <byte> vertsInFace = new List <byte>();
                        for (int k = 0; k < indexCount; k++)
                        {
                            byte vertIndex = br.ReadByte();
                            vertsInFace.Add(vertIndex);

                            float texCoordX = br.ReadSingle(); float texCoordY = br.ReadSingle();

                            float lmCoordX = 0.0f; float lmCoordY = 0.0f;
                            if ((faceFlags & 16) != 0)
                            {
                                lmCoordX = br.ReadSingle(); lmCoordY = br.ReadSingle();
                            }
                        }

                        Coordinate norm = new Coordinate(planeEq0, planeEq2, planeEq1);

                        if (Math.Abs((float)norm.LengthSquared()) > 0.001f)
                        {
                            if (Math.Abs((double)norm.LengthSquared() - 1) > 0.001)
                            {
                                throw new Exception(norm.LengthSquared().ToString());
                            }

                            Face newFace = new Face(map.IDGenerator.GetNextFaceID());

                            foreach (byte vertInd in vertsInFace)
                            {
                                newFace.Vertices.Insert(0, new Vertex(vertices[vertInd], newFace));
                            }

                            newFace.Plane = new Plane(newFace.Vertices[0].Location, newFace.Vertices[1].Location, newFace.Vertices[2].Location);

                            newFace.UpdateBoundingBox();

                            /*if ((faceFlags & 4) == 0)
                             * {
                             *  Entity entity = new Entity(map.IDGenerator.GetNextObjectID());
                             *  entity.Colour = Color.Lime;
                             *  entity.Origin = newFace.BoundingBox.Center;
                             *  entity.UpdateBoundingBox();
                             *  entity.SetParent(map.WorldSpawn);
                             *
                             *  Property newProperty = new Property();
                             *  newProperty.Key = "normal";
                             *  newProperty.Value = newFace.Plane.Normal.ToString();
                             *  entity.EntityData.Properties.Add(newProperty);
                             *
                             *  var direction = newFace.Plane.GetClosestAxisToNormal();
                             *  var tempV = direction == Coordinate.UnitZ ? -Coordinate.UnitY : -Coordinate.UnitZ;
                             *  var uAxis = newFace.Plane.Normal.Cross(tempV).Normalise();
                             *  var vAxis = uAxis.Cross(newFace.Plane.Normal).Normalise();
                             *
                             *  newProperty = new Property();
                             *  newProperty.Key = "uaxis";
                             *  newProperty.Value = uAxis.ToString();
                             *  entity.EntityData.Properties.Add(newProperty);
                             *
                             *  newProperty = new Property();
                             *  newProperty.Key = "vaxis";
                             *  newProperty.Value = vAxis.ToString();
                             *  entity.EntityData.Properties.Add(newProperty);
                             * }*/

                            Coordinate uNorm = new Coordinate(uTexPlane0, uTexPlane2, uTexPlane1).Normalise();
                            Coordinate vNorm = new Coordinate(vTexPlane0, vTexPlane2, vTexPlane1).Normalise();
                            if (Math.Abs((double)(uNorm.LengthSquared() - vNorm.LengthSquared())) > 0.001)
                            {
                                throw new Exception(uNorm.LengthSquared().ToString() + " " + vNorm.LengthSquared().ToString());
                            }

                            newFace.Texture.Name = (faceFlags & 4) != 0 ? "tooltextures/remove_face" :
                                                   invisibleCollision  ? "tooltextures/invisible_collision" :
                                                   materials[materialInd];
                            newFace.AlignTextureToWorld();
                            //TODO: add warning?
                            //if (texRotY != texRotX) throw new Exception((texRotX - texRotY).ToString());

                            newFace.Texture.UAxis    = uNorm * (decimal)Math.Cos(-texRotY * Math.PI / 180.0) + vNorm * (decimal)Math.Sin(-texRotY * Math.PI / 180.0);
                            newFace.Texture.VAxis    = vNorm * (decimal)Math.Cos(-texRotY * Math.PI / 180.0) - uNorm * (decimal)Math.Sin(-texRotY * Math.PI / 180.0);
                            newFace.Texture.XScale   = texScaleX / 2;
                            newFace.Texture.YScale   = texScaleY / 2;
                            newFace.Texture.XShift   = -texPosX * 2 / texScaleX;
                            newFace.Texture.YShift   = texPosY * 2 / texScaleY;
                            newFace.Texture.Rotation = (decimal)texRotY;

                            newFace.Transform(new UnitScale(Coordinate.One, newFace.BoundingBox.Center), TransformFlags.None);

                            faces.Add(newFace);
                        }
                    }

                    Solid newSolid = new Solid(map.IDGenerator.GetNextObjectID());
                    foreach (Face face in faces)
                    {
                        face.Parent = newSolid;
                        newSolid.Faces.Add(face);
                    }
                    newSolid.Colour = Colour.GetRandomBrushColour();
                    newSolid.UpdateBoundingBox();

                    if (newSolid.IsValid())
                    {
                        newSolid.SetParent(map.WorldSpawn);

                        newSolid.Transform(new UnitScale(Coordinate.One, newSolid.BoundingBox.Center), TransformFlags.None);
                    }
                    else
                    {
                        var offset = newSolid.BoundingBox.Center;
                        // Not a valid solid, decompose into tetrahedrons/etc
                        foreach (var face in faces)
                        {
                            var polygon = new Polygon(face.Vertices.Select(x => x.Location));
                            if (!polygon.IsValid() || !polygon.IsConvex())
                            {
                                // tetrahedrons
                                foreach (var triangle in face.GetTrianglesReversed())
                                {
                                    var tf = new Face(map.IDGenerator.GetNextFaceID());
                                    tf.Plane = new Plane(triangle[0].Location, triangle[1].Location, triangle[2].Location);
                                    tf.Vertices.AddRange(triangle.Select(x => new Vertex(x.Location, tf)));
                                    tf.Texture = face.Texture.Clone();
                                    tf.UpdateBoundingBox();
                                    newSolid = SolidifyFace(map, tf, offset);
                                    newSolid.SetParent(map.WorldSpawn);
                                    newSolid.UpdateBoundingBox();

                                    newSolid.Transform(new UnitScale(Coordinate.One, newSolid.BoundingBox.Center), TransformFlags.None);
                                }
                            }
                            else
                            {
                                // cone/pyramid/whatever
                                newSolid = SolidifyFace(map, face, offset);
                                newSolid.SetParent(map.WorldSpawn);
                                newSolid.UpdateBoundingBox();

                                newSolid.Transform(new UnitScale(Coordinate.One, newSolid.BoundingBox.Center), TransformFlags.None);
                            }
                        }
                    }
                }
                else
                {
                    br.BaseStream.Seek(size, SeekOrigin.Current);
                }
            }

            return(map);
        }
示例#10
0
        private void Read(DataStructures.MapObjects.Map map, StreamReader reader)
        {
            var points       = new List <Coordinate>();
            var faces        = new List <ObjFace>();
            var currentGroup = "default";
            var scale        = 100m;

            string line;

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

                line = CleanLine(line);
                string keyword, values;
                SplitLine(line, out keyword, out 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
                    points.Add(Coordinate.Parse(vals[0], vals[1], vals[2]) * 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.Colour = solid.Colour;
                    face.AlignTexture();
                }
                solid.SetParent(map.WorldSpawn);
            }
        }
示例#11
0
        protected override void SaveToStream(Stream stream, DataStructures.MapObjects.Map map)
        {
            /*
             * // Csg version
             *
             * var csg = new CsgSolid();
             * foreach (var mo in map.WorldSpawn.Find(x => x is Solid).OfType<Solid>())
             * {
             *  csg = csg.Union(new CsgSolid(mo.Faces.Select(x => new Polygon(x.Vertices.Select(v => v.Location)))));
             * }
             *
             * using (var sw = new StreamWriter(stream))
             * {
             *  foreach (var polygon in csg.Polygons)
             *  {
             *      foreach (var v in polygon.Vertices)
             *      {
             *          sw.Write("v ");
             *          sw.Write(v.X.ToString("0.0000", CultureInfo.InvariantCulture));
             *          sw.Write(' ');
             *          sw.Write(v.Y.ToString("0.0000", CultureInfo.InvariantCulture));
             *          sw.Write(' ');
             *          sw.Write(v.Z.ToString("0.0000", CultureInfo.InvariantCulture));
             *          sw.WriteLine();
             *      }
             *
             *      sw.Write("f ");
             *      for (int i = polygon.Vertices.Count; i > 0; i--)
             *      {
             *          sw.Write(-i);
             *          sw.Write(' ');
             *      }
             *      sw.WriteLine();
             *      sw.WriteLine();
             *  }
             * }
             */

            // Semi-recoverable version
            using (var sw = new StreamWriter(stream))
            {
                sw.WriteLine("# Chisel Object Export");
                sw.WriteLine("# Scale: 1");
                sw.WriteLine();

                foreach (var solid in map.WorldSpawn.Find(x => x is Solid).OfType <Solid>())
                {
                    sw.Write("g solid_");
                    sw.Write(solid.ID);
                    sw.WriteLine();

                    foreach (var face in solid.Faces)
                    {
                        foreach (var v in face.Vertices)
                        {
                            sw.Write("v ");
                            sw.Write(v.Location.X.ToString("0.0000", CultureInfo.InvariantCulture));
                            sw.Write(' ');
                            sw.Write(v.Location.Y.ToString("0.0000", CultureInfo.InvariantCulture));
                            sw.Write(' ');
                            sw.Write(v.Location.Z.ToString("0.0000", CultureInfo.InvariantCulture));
                            sw.WriteLine();
                        }

                        sw.Write("f ");
                        for (var i = 1; i <= face.Vertices.Count; i++)
                        {
                            sw.Write(-i);
                            sw.Write(' ');
                        }
                        sw.WriteLine();
                        sw.WriteLine();
                    }
                }
            }
        }
示例#12
0
 protected override void SaveToStream(Stream stream, DataStructures.MapObjects.Map map, DataStructures.GameData.GameData gameData, TextureCollection textureCollection)
 {
     throw new NotImplementedException("don't save to 3dw, ew");
 }
示例#13
0
        protected override DataStructures.MapObjects.Map GetFromStream(Stream stream, IEnumerable <string> modelDirs, out Image[] lightmaps)
        {
            lightmaps = null;
            var map = new DataStructures.MapObjects.Map();

            map.CordonBounds = new Box(Coordinate.One * -16384, Coordinate.One * 16384);
            BinaryReader br = new BinaryReader(stream);

            //header
            UInt16 mapVersion   = br.ReadUInt16();
            byte   mapFlags     = br.ReadByte();
            Int32  nameCount    = br.ReadInt32();
            Int32  nameOffset   = br.ReadInt32();
            Int32  objectCount  = br.ReadInt32();
            Int32  objectOffset = br.ReadInt32();

            //get names, needed to understand the objects
            List <string> names = new List <string>();

            br.BaseStream.Seek(nameOffset, SeekOrigin.Begin);
            for (int i = 0; i < nameCount; i++)
            {
                string name = br.ReadNullTerminatedString();
                names.Add(name);
            }

            //now we can parse the object table
            List <string> materials = new List <string>();
            List <Tuple <int, string> > meshReferences = new List <Tuple <int, string> >();
            Dictionary <int, Group>     groups         = new Dictionary <int, Group>();
            Dictionary <int, int>       visgroups      = new Dictionary <int, int>();

            br.BaseStream.Seek(objectOffset, SeekOrigin.Begin);
            long objectStartPos = br.BaseStream.Position;

            for (int i = 0; i < objectCount; i++)
            {
                int    index = br.ReadInt32() - 1;
                int    size  = br.ReadInt32();
                string name  = null;
                if (index >= 0 && index < names.Count)
                {
                    name = names[index];
                }

                if (name == "group")
                {
                    byte  flags      = br.ReadByte();
                    Int32 groupIndex = br.ReadInt32();

                    Group newGroup = new Group(map.IDGenerator.GetNextObjectID());
                    newGroup.SetParent(map.WorldSpawn);

                    groups.Add(i, newGroup);
                }
                else if (name == "visgroup")
                {
                    byte   flags = br.ReadByte();
                    string groupName = names[br.ReadInt32() - 1];
                    byte   colorR = br.ReadByte(); byte colorG = br.ReadByte(); byte colorB = br.ReadByte();

                    Visgroup newGroup = new Visgroup()
                    {
                        Name = groupName, ID = visgroups.Count + 1
                    };
                    newGroup.Colour = System.Drawing.Color.FromArgb(colorR, colorG, colorB);
                    map.Visgroups.Add(newGroup);
                    visgroups.Add(i, newGroup.ID);
                }
                else if (name == "meshreference")
                {
                    byte flags = br.ReadByte();

                    Int32 groupNameInd  = br.ReadInt32() - 1;
                    Int32 objectNameInd = br.ReadInt32() - 1;

                    byte limbCount = br.ReadByte();

                    meshReferences.Add(new Tuple <int, string>(i, names[objectNameInd]));
                }
                else if (name == "material")
                {
                    byte   materialFlags      = br.ReadByte();
                    Int32  groupIndex         = br.ReadInt32();
                    string objectName         = names[br.ReadInt32() - 1];
                    Int32  extensionNameIndex = -1;
                    if ((materialFlags & 2) != 0)
                    {
                        extensionNameIndex = br.ReadInt32(); //TODO: what the heck is this
                    }
                    materials.Add(objectName);
                }
                else
                {
                    br.BaseStream.Seek(size, SeekOrigin.Current);
                }
            }
            br.BaseStream.Position = objectStartPos;
            for (int i = 0; i < objectCount; i++)
            {
                int    index = br.ReadInt32() - 1;
                int    size  = br.ReadInt32();
                string name  = null;
                if (index >= 0 && index < names.Count)
                {
                    name = names[index];
                }

                if (name == "mesh")
                {
                    Property newProperty;

                    long startPos = br.BaseStream.Position;

                    byte flags = br.ReadByte();

                    Entity entity = new Entity(map.IDGenerator.GetNextObjectID());
                    entity.ClassName       = "model";
                    entity.EntityData.Name = "model";
                    entity.Colour          = Colour.GetDefaultEntityColour();

                    Int32 keyCount = br.ReadInt32();
                    for (int j = 0; j < keyCount; j++)
                    {
                        Int32 keyNameInd  = br.ReadInt32() - 1;
                        Int32 keyValueInd = br.ReadInt32() - 1;
                        if (names[keyNameInd] != "classname")
                        {
                            newProperty       = new Property();
                            newProperty.Key   = names[keyNameInd];
                            newProperty.Value = names[keyValueInd];

                            if (newProperty.Key == "file")
                            {
                                newProperty.Value = System.IO.Path.GetFileNameWithoutExtension(newProperty.Value);
                            }

                            entity.EntityData.Properties.Add(newProperty);
                        }
                    }

                    Int32 groupIndex    = br.ReadInt32() - 1;
                    Int32 visgroupIndex = br.ReadInt32() - 1;
                    if (visgroups.ContainsKey(visgroupIndex))
                    {
                        entity.Visgroups.Add(visgroups[visgroupIndex]);
                    }

                    byte red = br.ReadByte(); byte green = br.ReadByte(); byte blue = br.ReadByte();

                    Int32 meshRefIndex = br.ReadInt32() - 1;

                    float x = br.ReadSingle();
                    float z = br.ReadSingle();
                    float y = br.ReadSingle();
                    if (entity != null)
                    {
                        entity.Origin = new Coordinate((decimal)x, (decimal)y, (decimal)z);
                    }

                    if (entity.EntityData.GetPropertyValue("file") == null)
                    {
                        newProperty       = new Property();
                        newProperty.Key   = "file";
                        newProperty.Value = meshReferences.Find(q => q.Item1 == meshRefIndex).Item2;

                        entity.EntityData.Properties.Add(newProperty);
                    }

                    float pitch = br.ReadSingle();
                    float yaw   = br.ReadSingle();
                    float roll  = br.ReadSingle();
                    newProperty       = new Property();
                    newProperty.Key   = "angles";
                    newProperty.Value = pitch.ToString() + " " + yaw.ToString() + " " + roll.ToString();

                    entity.EntityData.Properties.Add(newProperty);

                    float xScale = 1.0f;
                    float yScale = 1.0f;
                    float zScale = 1.0f;

                    if ((flags & 1) == 0)
                    {
                        xScale = br.ReadSingle();
                        yScale = br.ReadSingle();
                        zScale = br.ReadSingle();
                    }

                    newProperty       = new Property();
                    newProperty.Key   = "scale";
                    newProperty.Value = xScale.ToString() + " " + yScale.ToString() + " " + zScale.ToString();

                    entity.EntityData.Properties.Add(newProperty);

                    br.BaseStream.Position += size - (br.BaseStream.Position - startPos);

                    entity.UpdateBoundingBox();

                    if (groups.ContainsKey(groupIndex))
                    {
                        entity.SetParent(groups[groupIndex]);
                    }
                    else
                    {
                        entity.SetParent(map.WorldSpawn);
                    }
                }
                else if (name == "entity")
                {
                    byte  flags = br.ReadByte();
                    float x     = br.ReadSingle();
                    float z     = br.ReadSingle();
                    float y     = br.ReadSingle();

                    Entity entity = new Entity(map.IDGenerator.GetNextObjectID());
                    entity.Colour = Colour.GetDefaultEntityColour();
                    entity.Origin = new Coordinate((decimal)x, (decimal)y, (decimal)z);

                    Int32 keyCount = br.ReadInt32();
                    for (int j = 0; j < keyCount; j++)
                    {
                        Int32 keyNameInd  = br.ReadInt32() - 1;
                        Int32 keyValueInd = br.ReadInt32() - 1;
                        if (names[keyNameInd] == "classname")
                        {
                            entity.ClassName       = names[keyValueInd];
                            entity.EntityData.Name = names[keyValueInd];
                        }
                        else
                        {
                            Property newProperty = new Property();
                            newProperty.Key   = names[keyNameInd];
                            newProperty.Value = names[keyValueInd];
                            entity.EntityData.Properties.Add(newProperty);
                        }
                    }

                    Int32 groupIndex    = br.ReadInt32() - 1;
                    Int32 visgroupIndex = br.ReadInt32() - 1;
                    if (visgroups.ContainsKey(visgroupIndex))
                    {
                        entity.Visgroups.Add(visgroups[visgroupIndex]);
                    }

                    entity.UpdateBoundingBox();
                    if (groups.ContainsKey(groupIndex))
                    {
                        entity.SetParent(groups[groupIndex]);
                    }
                    else
                    {
                        entity.SetParent(map.WorldSpawn);
                    }
                }
                else if (name == "brush")
                {
                    bool invisibleCollision = false;

                    byte  brushFlags = br.ReadByte(); //TODO: ???
                    Int32 keys       = br.ReadInt32();
                    for (int j = 0; j < keys; j++)
                    {
                        Int32  keyNameInd  = br.ReadInt32();
                        Int32  keyValueInd = br.ReadInt32();
                        string keyName     = names[keyNameInd - 1];
                        if (keyName.Equals("classname", StringComparison.OrdinalIgnoreCase))
                        {
                            string keyValue = names[keyValueInd - 1];
                            if (keyValue.Equals("field_hit", StringComparison.OrdinalIgnoreCase))
                            {
                                invisibleCollision = true;
                            }
                        }
                    }
                    Int32 groupIndex    = br.ReadInt32() - 1;
                    Int32 visgroupIndex = br.ReadInt32() - 1;

                    byte red = br.ReadByte(); byte green = br.ReadByte(); byte blue = br.ReadByte();

                    List <Coordinate> vertices = new List <Coordinate>();
                    byte vertexCount           = br.ReadByte();
                    for (int j = 0; j < vertexCount; j++)
                    {
                        decimal x = (decimal)br.ReadSingle(); decimal z = (decimal)br.ReadSingle(); decimal y = (decimal)br.ReadSingle();
                        vertices.Add(new Coordinate(x, y, z));
                    }
                    List <Face> faces     = new List <Face>();
                    byte        faceCount = br.ReadByte();
                    for (int j = 0; j < faceCount; j++)
                    {
                        byte faceFlags = br.ReadByte();

                        //TODO: maybe we need these unused bits for something idk
                        decimal planeEq0 = (decimal)br.ReadSingle(); decimal planeEq1 = (decimal)br.ReadSingle(); decimal planeEq2 = (decimal)br.ReadSingle(); decimal planeEq3 = (decimal)br.ReadSingle();

                        decimal texPosX = (decimal)br.ReadSingle(); decimal texPosY = (decimal)br.ReadSingle();
                        decimal texScaleX = (decimal)br.ReadSingle(); decimal texScaleY = (decimal)br.ReadSingle();
                        float   texRotX = br.ReadSingle(); float texRotY = br.ReadSingle();

                        decimal uTexPlane0 = (decimal)br.ReadSingle(); decimal uTexPlane1 = (decimal)br.ReadSingle(); decimal uTexPlane2 = (decimal)br.ReadSingle(); decimal uTexPlane3 = (decimal)br.ReadSingle();
                        decimal vTexPlane0 = (decimal)br.ReadSingle(); decimal vTexPlane1 = (decimal)br.ReadSingle(); decimal vTexPlane2 = (decimal)br.ReadSingle(); decimal vTexPlane3 = (decimal)br.ReadSingle();

                        float luxelSize = br.ReadSingle();

                        Int32 smoothGroupInd = br.ReadInt32();
                        Int32 materialInd    = br.ReadInt32() - 1;

                        Int32 lightmapInd = -1;
                        if ((faceFlags & 16) != 0)
                        {
                            lightmapInd = br.ReadInt32();
                        }

                        byte        indexCount  = br.ReadByte();
                        List <byte> vertsInFace = new List <byte>();
                        for (int k = 0; k < indexCount; k++)
                        {
                            byte vertIndex = br.ReadByte();
                            vertsInFace.Add(vertIndex);

                            float texCoordX = br.ReadSingle(); float texCoordY = br.ReadSingle();

                            float lmCoordX = 0.0f; float lmCoordY = 0.0f;
                            if ((faceFlags & 16) != 0)
                            {
                                lmCoordX = br.ReadSingle(); lmCoordY = br.ReadSingle();
                            }
                        }

                        Coordinate norm = new Coordinate(planeEq0, planeEq2, planeEq1);

                        if (Math.Abs((float)norm.LengthSquared()) > 0.001f)
                        {
                            if (Math.Abs((double)norm.LengthSquared() - 1) > 0.001)
                            {
                                throw new Exception(norm.LengthSquared().ToString());
                            }

                            Face newFace = new Face(map.IDGenerator.GetNextFaceID());

                            foreach (byte vertInd in vertsInFace)
                            {
                                newFace.Vertices.Insert(0, new Vertex(vertices[vertInd], newFace));
                            }

                            newFace.Plane = new Plane(newFace.Vertices[0].Location, newFace.Vertices[1].Location, newFace.Vertices[2].Location);

                            newFace.UpdateBoundingBox();

                            Coordinate uNorm = new Coordinate(uTexPlane0, uTexPlane2, uTexPlane1).Normalise();
                            Coordinate vNorm = new Coordinate(vTexPlane0, vTexPlane2, vTexPlane1).Normalise();
                            if (Math.Abs((double)(uNorm.LengthSquared() - vNorm.LengthSquared())) > 0.001)
                            {
                                throw new Exception(uNorm.LengthSquared().ToString() + " " + vNorm.LengthSquared().ToString());
                            }

                            newFace.Texture.Name = (faceFlags & 4) != 0 ? "tooltextures/remove_face" :
                                                   invisibleCollision ? "tooltextures/invisible_collision" :
                                                   materials[materialInd];
                            newFace.AlignTextureToWorld();

                            newFace.Texture.UAxis = uNorm * (decimal)Math.Cos(-texRotX * Math.PI / 180.0) + vNorm * (decimal)Math.Sin(-texRotX * Math.PI / 180.0);
                            newFace.Texture.VAxis = vNorm * (decimal)Math.Cos(-texRotX * Math.PI / 180.0) - uNorm * (decimal)Math.Sin(-texRotX * Math.PI / 180.0);

                            //huh?????
                            if (Math.Abs(texScaleX) < 0.0001m)
                            {
                                if (Math.Abs(texScaleY) < 0.0001m)
                                {
                                    texScaleX = 1m;
                                    texScaleY = 1m;
                                }
                                else
                                {
                                    texScaleX = texScaleY;
                                }
                            }
                            else if (Math.Abs(texScaleY) < 0.0001m)
                            {
                                texScaleY = texScaleX;
                            }
                            newFace.Texture.XScale   = texScaleX / 2;
                            newFace.Texture.YScale   = texScaleY / 2;
                            newFace.Texture.XShift   = -texPosX * 2 / texScaleX;
                            newFace.Texture.YShift   = texPosY * 2 / texScaleY;
                            newFace.Texture.Rotation = (decimal)texRotX;

                            //seriously, what the F**K???????????
                            if ((texRotX - texRotY) > 120.0f)
                            {
                                newFace.Texture.XScale   *= -1m;
                                newFace.Texture.YScale   *= -1m;
                                newFace.Texture.Rotation -= 180m;
                                newFace.Texture.UAxis     = -newFace.Texture.UAxis;
                            }
                            else if ((texRotY - texRotX) > 120.0f)
                            {
                                newFace.Texture.XScale   *= -1m;
                                newFace.Texture.YScale   *= -1m;
                                newFace.Texture.Rotation -= 180m;
                                newFace.Texture.VAxis     = -newFace.Texture.VAxis;
                            }

                            newFace.Transform(new UnitScale(Coordinate.One, newFace.BoundingBox.Center), TransformFlags.None);

                            faces.Add(newFace);
                        }
                    }

                    Solid newSolid = new Solid(map.IDGenerator.GetNextObjectID());
                    foreach (Face face in faces)
                    {
                        face.Parent = newSolid;
                        newSolid.Faces.Add(face);
                    }
                    if (visgroups.ContainsKey(visgroupIndex))
                    {
                        newSolid.Visgroups.Add(visgroups[visgroupIndex]);
                    }
                    newSolid.Colour = Colour.GetRandomBrushColour();
                    newSolid.UpdateBoundingBox();

                    MapObject parent = map.WorldSpawn;
                    if (groups.ContainsKey(groupIndex))
                    {
                        parent = groups[groupIndex];
                    }

                    if (newSolid.IsValid())
                    {
                        newSolid.SetParent(parent);

                        newSolid.Transform(new UnitScale(Coordinate.One, newSolid.BoundingBox.Center), TransformFlags.None);
                    }
                    else
                    {
                        var offset = newSolid.BoundingBox.Center;
                        // Not a valid solid, decompose into tetrahedrons/etc
                        foreach (var face in faces)
                        {
                            var polygon = new Polygon(face.Vertices.Select(x => x.Location));
                            if (!polygon.IsValid() || !polygon.IsConvex())
                            {
                                // tetrahedrons
                                foreach (var triangle in face.GetTrianglesReversed())
                                {
                                    var tf = new Face(map.IDGenerator.GetNextFaceID());
                                    tf.Plane = new Plane(triangle[0].Location, triangle[1].Location, triangle[2].Location);
                                    tf.Vertices.AddRange(triangle.Select(x => new Vertex(x.Location, tf)));
                                    tf.Texture = face.Texture.Clone();
                                    tf.UpdateBoundingBox();
                                    newSolid = SolidifyFace(map, tf, offset);
                                    newSolid.SetParent(parent);
                                    newSolid.UpdateBoundingBox();

                                    newSolid.Transform(new UnitScale(Coordinate.One, newSolid.BoundingBox.Center), TransformFlags.None);
                                }
                            }
                            else
                            {
                                // cone/pyramid/whatever
                                newSolid = SolidifyFace(map, face, offset);
                                newSolid.SetParent(parent);
                                newSolid.UpdateBoundingBox();

                                newSolid.Transform(new UnitScale(Coordinate.One, newSolid.BoundingBox.Center), TransformFlags.None);
                            }
                        }
                    }
                }
                else
                {
                    if (name == "terrain")
                    {
                        MapProvider.warnings = "This map contains displacements, which are currently not supported. The map will appear incomplete.";
                    }
                    br.BaseStream.Seek(size, SeekOrigin.Current);
                }
            }

            return(map);
        }
示例#14
0
        protected override DataStructures.MapObjects.Map GetFromStream(Stream stream, IEnumerable <string> modelDirs, out Image[] lightmaps)
        {
            BinaryReader reader = new BinaryReader(stream);

            if (reader.ReadFixedLengthString(Encoding.ASCII, 3) != "CBR")
            {
                throw new ProviderException("CBR file is corrupted/invalid!");
            }
            uint revision = reader.ReadUInt32();

            // Lightmaps
            bool lightmapped = reader.ReadByte() > (byte)Lightmapped.No;

            if (lightmapped)
            {
                lightmaps = new Image[4];
                for (int i = 0; i < 4; i++)
                {
                    lightmaps[i] = Image.FromStream(new MemoryStream(reader.ReadBytes(reader.ReadInt32())));
                }
            }
            else
            {
                lightmaps = null;
            }

            // Texture dictionary
            int texSize = reader.ReadInt32();

            string[] textures = new string[texSize];
            for (int i = 0; i < texSize; i++)
            {
                textures[i] = reader.ReadNullTerminatedString();
            }

            DataStructures.MapObjects.Map map = new DataStructures.MapObjects.Map();
            map.WorldSpawn = new World(map.IDGenerator.GetNextObjectID());

            // Solids
            List <MapObject> solids = new List <MapObject>();
            int solidCount          = reader.ReadInt32();

            for (int i = 0; i < solidCount; i++)
            {
                Solid s = new Solid(map.IDGenerator.GetNextObjectID());
                s.Colour = Colour.GetRandomBrushColour();
                int faceCount = reader.ReadInt32();
                for (int j = 0; j < faceCount; j++)
                {
                    Face f = new Face(map.IDGenerator.GetNextFaceID());
                    f.Colour           = s.Colour;
                    f.Texture.Name     = textures[reader.ReadInt32()];
                    f.Texture.UAxis    = reader.ReadCoordinate();
                    f.Texture.VAxis    = reader.ReadCoordinate();
                    f.Texture.XShift   = reader.ReadDecimal();
                    f.Texture.YShift   = reader.ReadDecimal();
                    f.Texture.XScale   = reader.ReadDecimal();
                    f.Texture.YScale   = reader.ReadDecimal();
                    f.Texture.Rotation = reader.ReadDecimal();
                    int vertexCount = reader.ReadInt32();
                    for (int k = 0; k < vertexCount; k++)
                    {
                        Vertex v = new Vertex(reader.ReadCoordinate(), f);
                        if (lightmapped)
                        {
                            v.LMU      = reader.ReadSingle();
                            v.LMV      = reader.ReadSingle();
                            v.TextureU = (decimal)reader.ReadSingle();
                            v.TextureV = (decimal)reader.ReadSingle();
                        }
                        f.Vertices.Add(v);
                    }
                    f.Plane  = new Plane(f.Vertices[0].Location, f.Vertices[1].Location, f.Vertices[2].Location);
                    f.Parent = s;
                    s.Faces.Add(f);
                    f.UpdateBoundingBox();
                }
                s.SetParent(map.WorldSpawn, false);
                s.UpdateBoundingBox(false);
                solids.Add(s);
            }

            // Entities
            List <MapObject> entities = new List <MapObject>(0);
            string           read;
            bool             isStillSolid = true;

            for (int i = 0; i < 2; i++)
            {
                while ((read = reader.ReadNullTerminatedString()) != "")
                {
                    List <Property> properties = new List <Property>();
                    byte            propertyType;
                    while ((propertyType = reader.ReadByte()) != 255)
                    {
                        properties.Add(new Property()
                        {
                            name = reader.ReadNullTerminatedString(),
                            type = (VariableType)propertyType
                        });
                    }

                    // Entries
                    int entitiesOfType = reader.ReadInt32();
                    entities.Capacity += entitiesOfType;
                    for (int j = 0; j < entitiesOfType; j++)
                    {
                        Entity e = new Entity(map.IDGenerator.GetNextObjectID());
                        e.Colour          = Colour.GetDefaultEntityColour();
                        e.ClassName       = read;
                        e.EntityData.Name = read;
                        if (isStillSolid)
                        {
                            int entitySolids = reader.ReadInt32();
                            for (int k = 0; k < entitySolids; k++)
                            {
                                solids[reader.ReadInt32()].SetParent(e);
                            }
                        }
                        e.SetParent(map.WorldSpawn);
                        foreach (Property property in properties)
                        {
                            string propertyVal;
                            switch (property.type)
                            {
                            case VariableType.Bool:
                                propertyVal = reader.ReadBoolean() ? "Yes" : "No";
                                break;

                            case VariableType.Color255:
                                propertyVal = DataStructures.MapObjects.Property.FromColor(reader.ReadRGBAColour());
                                break;

                            case VariableType.Float:
                                propertyVal = reader.ReadSingle().ToString();
                                break;

                            case VariableType.Integer:
                                propertyVal = reader.ReadInt32().ToString();
                                break;

                            case VariableType.String:
                                propertyVal = reader.ReadNullTerminatedString();
                                break;

                            case VariableType.Vector:
                                propertyVal = DataStructures.MapObjects.Property.FromCoordinate(reader.ReadCoordinate());
                                break;

                            case VariableType.Choices:
                                // TODO: Bullshit
                                throw new NotImplementedException();

                            default:
                                propertyVal = "";
                                break;
                            }
                            e.EntityData.SetPropertyValue(property.name, propertyVal);
                        }
                        e.UpdateBoundingBox();
                        entities.Add(e);
                    }
                }
                isStillSolid = false;
            }

            // CBRE ONLY

            // Visgroup dictionary
            Visgroup currentParentVisgroup = null;

            while (true)
            {
                byte     hierarchyControl;
                Visgroup newGroup = null;
                while ((hierarchyControl = reader.ReadByte()) == HIERARCHY_PROCCEED)
                {
                    newGroup        = new Visgroup();
                    newGroup.Colour = Colour.GetRandomBrushColour();
                    newGroup.ID     = reader.ReadInt32();
                    newGroup.Name   = reader.ReadNullTerminatedString();
                    if (currentParentVisgroup != null)
                    {
                        newGroup.Parent = currentParentVisgroup;
                        currentParentVisgroup.Children.Add(newGroup);
                    }
                    else
                    {
                        map.Visgroups.Add(newGroup);
                    }
                }
                if (hierarchyControl == HIERARCHY_DOWN)
                {
                    currentParentVisgroup = newGroup;
                }
                else if (currentParentVisgroup != null)
                {
                    currentParentVisgroup = currentParentVisgroup.Parent;
                }
                else
                {
                    break;
                }
            }

            // Solid visgroups
            foreach (Solid mo in solids)
            {
                ReadVisgroups(reader, mo);
            }

            // Entity visgroups
            foreach (Entity e in entities)
            {
                ReadVisgroups(reader, e);
            }

            // Groups
            int directWorldGroups = reader.ReadInt32();

            for (int i = 0; i < directWorldGroups; i++)
            {
                Group currentParentGroup = new Group(map.IDGenerator.GetNextObjectID());
                currentParentGroup.SetParent(map.WorldSpawn);
                while (true)
                {
                    byte hierarchyControl;
                    while ((hierarchyControl = reader.ReadByte()) > HIERARCHY_UP)
                    {
                        if (hierarchyControl == IDENTIFIER_ENTITY)
                        {
                            entities[reader.ReadInt32()].SetParent(currentParentGroup);
                        }
                        else
                        {
                            solids[reader.ReadInt32()].SetParent(currentParentGroup);
                        }
                    }
                    if (hierarchyControl == HIERARCHY_DOWN)
                    {
                        Group newGroup = new Group(map.IDGenerator.GetNextObjectID());
                        newGroup.SetParent(currentParentGroup);
                        currentParentGroup = newGroup;
                    }
                    else if (currentParentGroup.Parent != map.WorldSpawn)
                    {
                        currentParentGroup = (Group)currentParentGroup.Parent;
                    }
                    else
                    {
                        break;
                    }
                }
            }

            stream.Close();
            return(map);
        }
示例#15
0
        protected override void SaveToStream(Stream stream, DataStructures.MapObjects.Map map, DataStructures.GameData.GameData gameData, TextureCollection textureCollection)
        {
            BinaryWriter writer = new BinaryWriter(stream);

            writer.WriteFixedLengthString(Encoding.ASCII, 3, "CBR");
            writer.Write(revision);

            // Lightmaps
            bool lightmapped = textureCollection != null && textureCollection.Lightmaps[0] != null;

            if (lightmapped)
            {
                writer.Write((byte)Lightmapped.Fully); // TODO: Determine changes from last render
                for (int i = 0; i < 4; i++)
                {
                    long prevPos = writer.Seek(0, SeekOrigin.Current);
                    writer.Write(0);
                    writer.Flush();
                    textureCollection.Lightmaps[i].Save(stream, ImageFormat.Png);
                    int imageOffset = (int)(writer.Seek(0, SeekOrigin.Current) - prevPos);
                    writer.Seek(-imageOffset, SeekOrigin.Current);
                    writer.Write(imageOffset - sizeof(int));
                    writer.Seek(0, SeekOrigin.End);
                }
            }
            else
            {
                writer.Write((byte)Lightmapped.No);
            }

            // Texture dictionary
            Dictionary <string, int> texDic     = new Dictionary <string, int>();
            StringBuilder            texBuilder = new StringBuilder();
            int texCount = 0;
            IEnumerator <string> textures = map.GetAllTextures().GetEnumerator();

            while (textures.MoveNext())
            {
                texBuilder.Append(textures.Current);
                texBuilder.Append('\0');
                texDic.Add(textures.Current, texCount);
                texCount++;
            }
            writer.Write(texCount);
            writer.WriteFixedLengthString(Encoding.UTF8, texBuilder.Length, texBuilder.ToString());

            // Solids
            List <MapObject> solids = map.WorldSpawn.Find(x => x is Solid);

            writer.Write(solids.Count);
            foreach (Solid s in solids)
            {
                writer.Write(s.Faces.Count);
                foreach (Face f in s.Faces)
                {
                    writer.Write(texDic[f.Texture.Name]);
                    writer.WriteCoordinate(f.Texture.UAxis);
                    writer.WriteCoordinate(f.Texture.VAxis);
                    writer.Write(f.Texture.XShift);
                    writer.Write(f.Texture.YShift);
                    writer.Write(f.Texture.XScale);
                    writer.Write(f.Texture.YScale);
                    writer.Write(f.Texture.Rotation);
                    writer.Write(f.Vertices.Count);
                    foreach (Vertex v in f.Vertices)
                    {
                        writer.WriteCoordinate(v.Location);
                        if (lightmapped)
                        {
                            writer.Write(v.LMU);
                            writer.Write(v.LMV);
                            writer.Write((float)v.TextureU);
                            writer.Write((float)v.TextureV);
                        }
                    }
                }
            }

            // Entities
            ISet <string>         foundEntityTypes = new HashSet <string>();
            List <GameDataObject> entityTypes      = new List <GameDataObject>();
            List <MapObject>      entites          = map.WorldSpawn.Find(x => x is Entity && x.ClassName != "");

            foreach (Entity e in entites)
            {
                Console.WriteLine(e.ClassName);
                Console.WriteLine(e.GameData.Name);
                if (!foundEntityTypes.Contains(e.ClassName))
                {
                    GameDataObject gdo = gameData.Classes.Find(x => x.Name == e.ClassName);
                    entityTypes.Add(gdo);
                    foundEntityTypes.Add(gdo.Name);
                }
            }
            // Move brush entities to front
            entityTypes.Sort((x, y) => (x.ClassType == ClassType.Solid ? -1 : 0));
            // For later use with groups
            Dictionary <Entity, int> entityIndices = new Dictionary <Entity, int>();
            int  entityIndicesCounter = 0;
            bool reachedRegular       = false;

            foreach (GameDataObject gdo in entityTypes)
            {
                if (!reachedRegular && gdo.ClassType != ClassType.Solid)
                {
                    reachedRegular = true;
                    writer.WriteNullTerminatedString("");
                }
                writer.WriteNullTerminatedString(gdo.Name);
                foreach (DataStructures.GameData.Property p in gdo.Properties)
                {
                    writer.Write((byte)p.VariableType);
                    writer.WriteNullTerminatedString(p.Name); // Switch from brush to regular entities
                }
                writer.Write((byte)255);                      // Property end byte

                // Entries
                List <MapObject> entitiesOfType = entites.FindAll(x => x.ClassName == gdo.Name);
                writer.Write(entitiesOfType.Count);
                foreach (Entity e in entitiesOfType)
                {
                    entityIndices.Add(e, entityIndicesCounter++);
                    if (e.GameData.ClassType == ClassType.Solid)
                    {
                        IEnumerable <MapObject> children = e.GetChildren();
                        writer.Write(children.Count());
                        foreach (MapObject mo in children)
                        {
                            int index = solids.FindIndex(x => x == mo);
                            writer.Write(index);
                        }
                    }
                    for (int i = 0; i < gdo.Properties.Count; i++)
                    {
                        DataStructures.MapObjects.Property property;
                        if (i < e.EntityData.Properties.Count && gdo.Properties[i].Name == e.EntityData.Properties[i].Key)
                        {
                            property = e.EntityData.Properties[i];
                        }
                        else
                        {
                            property = e.EntityData.Properties.Find(x => x.Key == gdo.Properties[i].Name);
                            if (property == null)
                            {
                                property       = new DataStructures.MapObjects.Property();
                                property.Key   = gdo.Properties[i].Name;
                                property.Value = gdo.Properties[i].DefaultValue;
                            }
                        }
                        switch (gdo.Properties[i].VariableType)
                        {
                        case VariableType.Bool:
                            writer.Write(property.Value == "Yes");
                            break;

                        case VariableType.Color255:
                            writer.WriteRGBAColour(property.GetColour(Color.Black));
                            break;

                        case VariableType.Float:
                            writer.Write(float.Parse(property.Value));
                            break;

                        case VariableType.Integer:
                            writer.Write(int.Parse(property.Value));
                            break;

                        case VariableType.String:
                            // TODO: Implement dictionary.
                            writer.WriteNullTerminatedString(property.Value);
                            break;

                        case VariableType.Vector:
                            writer.WriteCoordinate(property.GetCoordinate(Coordinate.Zero));
                            break;

                        case VariableType.Choices:
                            bool found = false;
                            for (int j = 0; j < gdo.Properties[i].Options.Count; j++)
                            {
                                if (property.Value == gdo.Properties[i].Options[j].Key)
                                {
                                    writer.Write((byte)j);
                                    found = true;
                                    break;
                                }
                            }
                            if (!found)
                            {
                                writer.Write((byte)255);
                            }
                            break;
                        }
                    }
                }
            }
            writer.WriteNullTerminatedString("");

            // CBRE ONLY

            // Visgroup dictionary
            // TODO: Visgroup IDs to indices
            Stack <IEnumerator <Visgroup> > visStack = new Stack <IEnumerator <Visgroup> >();

            visStack.Push(map.Visgroups.GetEnumerator());
            while (visStack.Count > 0)
            {
                IEnumerator <Visgroup> v = visStack.Pop();
                while (v.MoveNext())
                {
                    if (!v.Current.IsAutomatic)
                    {
                        writer.Write(HIERARCHY_PROCCEED);
                        writer.Write(v.Current.ID);
                        writer.WriteNullTerminatedString(v.Current.Name);
                        if (v.Current.Children.Count != 0)
                        {
                            writer.Write(HIERARCHY_DOWN);
                            visStack.Push(v);
                            v = v.Current.Children.GetEnumerator();
                        }
                    }
                }
                writer.Write(HIERARCHY_UP);
            }

            // Solid visgroups
            foreach (Solid s in map.WorldSpawn.FindAll().OfType <Solid>())
            {
                WriteVisgroups(writer, s);
            }

            // Entity visgroups
            foreach (GameDataObject entityType in entityTypes)
            {
                foreach (Entity e in entites.FindAll(x => x.ClassName == entityType.Name))
                {
                    WriteVisgroups(writer, e);
                }
            }

            // Groups
            IEnumerable <Group> groups = map.WorldSpawn.GetChildren().OfType <Group>();

            writer.Write(groups.Count());
            foreach (Group g in groups)
            {
                Stack <IEnumerator <MapObject> > groupStack = new Stack <IEnumerator <MapObject> >();
                groupStack.Push(g.GetChildren().GetEnumerator());
                while (groupStack.Count > 0)
                {
                    IEnumerator <MapObject> gg = groupStack.Pop();
                    while (gg.MoveNext())
                    {
                        if (gg.Current is Group)
                        {
                            writer.Write(HIERARCHY_DOWN);
                            groupStack.Push(gg);
                            gg = gg.Current.GetChildren().GetEnumerator();
                        }
                        else if (gg.Current is Entity)
                        {
                            writer.Write(IDENTIFIER_ENTITY);
                            writer.Write(entityIndices[(Entity)gg.Current]);
                        }
                        else
                        {
                            writer.Write(IDENTIFIER_SOLID);
                            writer.Write(solids.FindIndex(x => x == gg.Current));
                        }
                    }
                    writer.Write(HIERARCHY_UP);
                }
            }

            stream.Close();
        }
示例#16
0
        protected override void SaveToStream(Stream stream, DataStructures.MapObjects.Map map)
        {
            var groups = new List <Group>();
            var solids = new List <Solid>();
            var ents   = new List <Entity>();

            FlattenTree(map.WorldSpawn, solids, ents, groups);

            var fvi         = FileVersionInfo.GetVersionInfo(typeof(VmfProvider).Assembly.Location);
            var versioninfo = new GenericStructure("versioninfo");

            versioninfo.AddProperty("editorname", "Chisel");
            versioninfo.AddProperty("editorversion", fvi.ProductMajorPart.ToString(CultureInfo.InvariantCulture) + "." + fvi.ProductMinorPart.ToString(CultureInfo.InvariantCulture));
            versioninfo.AddProperty("editorbuild", fvi.ProductBuildPart.ToString(CultureInfo.InvariantCulture));
            versioninfo.AddProperty("mapversion", map.Version.ToString(CultureInfo.InvariantCulture));
            versioninfo.AddProperty("formatversion", "100");
            versioninfo.AddProperty("prefab", "0");

            var visgroups = new GenericStructure("visgroups");

            foreach (var visgroup in map.Visgroups.OrderBy(x => x.ID).Where(x => !x.IsAutomatic))
            {
                visgroups.Children.Add(WriteVisgroup(visgroup));
            }

            var viewsettings = new GenericStructure("viewsettings");

            viewsettings.AddProperty("bSnapToGrid", map.SnapToGrid ? "1" : "0");
            viewsettings.AddProperty("bShowGrid", map.Show2DGrid ? "1" : "0");
            viewsettings.AddProperty("bShow3DGrid", map.Show3DGrid ? "1" : "0");
            viewsettings.AddProperty("nGridSpacing", map.GridSpacing.ToString(CultureInfo.InvariantCulture));
            viewsettings.AddProperty("bIgnoreGrouping", map.IgnoreGrouping ? "1" : "0");
            viewsettings.AddProperty("bHideFaceMask", map.HideFaceMask ? "1" : "0");
            viewsettings.AddProperty("bHideNullTextures", map.HideNullTextures ? "1" : "0");
            viewsettings.AddProperty("bTextureLock", map.TextureLock ? "1" : "0");
            viewsettings.AddProperty("bTextureScalingLock", map.TextureScalingLock ? "1" : "0");

            var world = WriteWorld(map, solids, groups);

            var entities = ents.OrderBy(x => x.ID).Select(WriteEntity).ToList();

            var cameras = new GenericStructure("cameras");

            cameras.AddProperty("activecamera", map.Cameras.IndexOf(map.ActiveCamera).ToString(CultureInfo.InvariantCulture));
            foreach (var cam in map.Cameras)
            {
                var camera = new GenericStructure("camera");
                camera.AddProperty("position", "[" + FormatCoordinate(cam.EyePosition) + "]");
                camera.AddProperty("look", "[" + FormatCoordinate(cam.LookPosition) + "]");
                cameras.Children.Add(camera);
            }

            var cordon = new GenericStructure("cordon");

            cordon.AddProperty("mins", map.CordonBounds.Start.ToString());
            cordon.AddProperty("maxs", map.CordonBounds.End.ToString());
            cordon.AddProperty("active", map.Cordon ? "1" : "0");

            using (var sw = new StreamWriter(stream))
            {
                versioninfo.PrintToStream(sw);
                visgroups.PrintToStream(sw);
                viewsettings.PrintToStream(sw);
                world.PrintToStream(sw);
                entities.ForEach(e => e.PrintToStream(sw));
                cameras.PrintToStream(sw);
                cordon.PrintToStream(sw);
            }
        }
示例#17
0
        public static void SaveToFile(string filename, DataStructures.MapObjects.Map map, string format)
        {
            Scene scene = new Scene();

            Node rootNode = new Node();

            rootNode.Name  = "root";
            scene.RootNode = rootNode;

            Node newNode = new Node();

            Mesh mesh;
            int  vertOffset;

            string[] textures = map.GetAllTextures().ToArray();
            foreach (string texture in textures)
            {
                if (texture == "tooltextures/remove_face")
                {
                    continue;
                }

                Material material = new Material();
                material.Name = texture;
                TextureSlot textureSlot = new TextureSlot(texture +
                                                          (File.Exists(texture + ".png") ? ".png" : (File.Exists(texture + ".jpeg") ? ".jpeg" : ".jpg")),
                                                          TextureType.Diffuse,
                                                          0,
                                                          TextureMapping.Plane,
                                                          0,
                                                          1.0f,
                                                          TextureOperation.Multiply,
                                                          Assimp.TextureWrapMode.Wrap,
                                                          Assimp.TextureWrapMode.Wrap,
                                                          0);
                material.AddMaterialTexture(ref textureSlot);
                scene.Materials.Add(material);

                mesh = new Mesh();
                if (format != "obj") // .obj files should have no mesh names so they are one proper mesh
                {
                    mesh.Name = texture + "_mesh";
                }
                mesh.MaterialIndex = scene.MaterialCount - 1;
                vertOffset         = 0;

                List <int> indices = new List <int>();

                IEnumerable <Face> faces = map.WorldSpawn.Find(x => x is Solid).
                                           OfType <Solid>().
                                           SelectMany(x => x.Faces).
                                           Where(x => x.Texture.Name == texture);

                foreach (Face face in faces)
                {
                    foreach (Vertex v in face.Vertices)
                    {
                        mesh.Vertices.Add(new Vector3D((float)v.Location.X, (float)v.Location.Z, (float)v.Location.Y));
                        mesh.Normals.Add(new Vector3D((float)face.Plane.Normal.X, (float)face.Plane.Normal.Z, (float)face.Plane.Normal.Y));
                        mesh.TextureCoordinateChannels[0].Add(new Vector3D((float)v.TextureU, (float)v.TextureV, 0));
                    }
                    mesh.UVComponentCount[0] = 2;
                    foreach (uint ind in face.GetTriangleIndices())
                    {
                        indices.Add((int)ind + vertOffset);
                    }

                    vertOffset += face.Vertices.Count;
                }

                mesh.SetIndices(indices.ToArray(), 3);
                scene.Meshes.Add(mesh);

                newNode.MeshIndices.Add(scene.MeshCount - 1);
            }

            rootNode.Children.Add(newNode);

            new AssimpContext().ExportFile(scene, filename, format);
        }
示例#18
0
        protected override DataStructures.MapObjects.Map GetFromStream(Stream stream)
        {
            using (var reader = new StreamReader(stream))
            {
                var parent = new GenericStructure("Root");
                parent.Children.AddRange(GenericStructure.Parse(reader));
                // Sections from a Hammer map:
                // - world
                // - entity
                // - visgroups
                // - cordon
                // Not done yet
                // - versioninfo
                // - viewsettings
                // - cameras

                var map = new DataStructures.MapObjects.Map();

                var world = parent.GetChildren("world").FirstOrDefault();
                var entities = parent.GetChildren("entity");
                var visgroups = parent.GetChildren("visgroups").SelectMany(x => x.GetChildren("visgroup"));
                var cameras = parent.GetChildren("cameras").FirstOrDefault();
                var cordon = parent.GetChildren("cordon").FirstOrDefault();
                var viewsettings = parent.GetChildren("viewsettings").FirstOrDefault();

                foreach (var visgroup in visgroups)
                {
                    var vg = ReadVisgroup(visgroup);
                    if (vg.ID < 0 && vg.Name == "Auto") continue;
                    map.Visgroups.Add(vg);
                }

                if (world != null) map.WorldSpawn = ReadWorld(world, map.IDGenerator);
                foreach (var entity in entities)
                {
                    var ent = ReadEntity(entity, map.IDGenerator);
                    var groupid = entity.Children.Where(x => x.Name == "editor").Select(x => x.PropertyInteger("groupid")).FirstOrDefault();
                    var entParent = groupid > 0 ? map.WorldSpawn.Find(x => x.ID == groupid && x is Group).FirstOrDefault() ?? map.WorldSpawn : map.WorldSpawn;
                    ent.SetParent(entParent);
                }

                var activeCamera = 0;
                if (cameras != null)
                {
                    activeCamera = cameras.PropertyInteger("activecamera");
                    foreach (var cam in cameras.GetChildren("camera"))
                    {
                        var pos = cam.PropertyCoordinate("position");
                        var look = cam.PropertyCoordinate("look");
                        if (pos != null && look != null)
                        {
                            map.Cameras.Add(new Camera {EyePosition = pos, LookPosition = look});
                        }
                    }
                }
                if (!map.Cameras.Any())
                {
                    map.Cameras.Add(new Camera { EyePosition = Coordinate.Zero, LookPosition = Coordinate.UnitY });
                }
                if (activeCamera < 0 || activeCamera >= map.Cameras.Count)
                {
                    activeCamera = 0;
                }
                map.ActiveCamera = map.Cameras[activeCamera];

                if (cordon != null)
                {
                    var start = cordon.PropertyCoordinate("mins", map.CordonBounds.Start);
                    var end = cordon.PropertyCoordinate("maxs", map.CordonBounds.End);
                    map.CordonBounds = new Box(start, end);
                    map.Cordon = cordon.PropertyBoolean("active", map.Cordon);
                }

                if (viewsettings != null)
                {
                    map.SnapToGrid = viewsettings.PropertyBoolean("bSnapToGrid", map.SnapToGrid);
                    map.Show2DGrid = viewsettings.PropertyBoolean("bShowGrid", map.Show2DGrid);
                    map.Show3DGrid = viewsettings.PropertyBoolean("bShow3DGrid", map.Show3DGrid);
                    map.GridSpacing = viewsettings.PropertyDecimal("nGridSpacing", map.GridSpacing);
                    map.IgnoreGrouping = viewsettings.PropertyBoolean("bIgnoreGrouping", map.IgnoreGrouping);
                    map.HideFaceMask = viewsettings.PropertyBoolean("bHideFaceMask", map.HideFaceMask);
                    map.HideNullTextures = viewsettings.PropertyBoolean("bHideNullTextures", map.HideNullTextures);
                    map.TextureLock = viewsettings.PropertyBoolean("bTextureLock", map.TextureLock);
                    map.TextureScalingLock = viewsettings.PropertyBoolean("bTextureScalingLock", map.TextureScalingLock);
                }

                return map;
            }
        }
示例#19
0
 protected override void SaveToStream(Stream stream, DataStructures.MapObjects.Map map)
 {
     throw new Exception("don't save to 3dw, ew");
 }
示例#20
0
 protected abstract void SaveToStream(Stream stream, DataStructures.MapObjects.Map map);
示例#21
0
 protected abstract void SaveToStream(Stream stream, DataStructures.MapObjects.Map map, DataStructures.GameData.GameData gameData, TextureCollection textureCollection);
示例#22
0
        protected override DataStructures.MapObjects.Map GetFromStream(Stream stream, IEnumerable <string> modelDirs, out Image[] lightmaps)
        {
            lightmaps = null;
            var map = new DataStructures.MapObjects.Map();

            map.CordonBounds = new Box(Coordinate.One * -16384, Coordinate.One * 16384);
            BinaryReader br = new BinaryReader(stream);

            List <ModelReference> models = null;

            //header
            bool hasLightmap = Math.Abs(br.ReadSingle()) > 0.01f;

            if (hasLightmap)
            {
                UInt32 lightmapSize = br.ReadUInt32();
                stream.Position += lightmapSize;
            }
            int entityCount = (int)br.ReadSingle() - 2;

            for (int i = 0; i < entityCount; i++)
            {
                int         meshCount         = (int)br.ReadSingle();
                List <long> memblockLocations = new List <long>();
                for (int j = 0; j < meshCount; j++)
                {
                    stream.Position += 4;
                    memblockLocations.Add(stream.Position);
                    SkipMemblock(br);
                }

                bool isBrush = Math.Abs(br.ReadSingle()) > 0.01f;
                if (isBrush)
                {
                    Dictionary <int, List <Face> > faces = new Dictionary <int, List <Face> >();
                    long returnPosition = stream.Position;
                    for (int j = 0; j < meshCount; j++)
                    {
                        stream.Position = memblockLocations[j];
                        faces.Add(j, new List <Face>());
                        ReadMemblockMesh(br, map, faces[j]);
                    }
                    stream.Position = returnPosition;
                    SkipMemblock(br);
                    for (int j = 0; j < 2; j++)
                    {
                        stream.Position += 4;
                    }

                    float xTranslate = br.ReadSingle();
                    float zTranslate = br.ReadSingle();
                    float yTranslate = br.ReadSingle();

                    float xScale = br.ReadSingle();
                    float zScale = br.ReadSingle();
                    float yScale = br.ReadSingle();

                    for (int j = 8; j < 25; j++)
                    {
                        stream.Position += 4;
                    }
                    List <SubmeshTextureInfo> textures = new List <SubmeshTextureInfo>();
                    for (int j = 0; j < meshCount; j++)
                    {
                        SubmeshTextureInfo submeshTextureInfo = new SubmeshTextureInfo();

                        submeshTextureInfo.TextureName = System.IO.Path.GetFileNameWithoutExtension(br.ReadLine());
                        float flags        = br.ReadSingle();
                        bool  faceIsHidden = Math.Abs(flags - 1) < 0.01f;
                        bool  faceIsLit    = Math.Abs(flags - 800) < 0.01f;
                        if (faceIsLit)
                        {
                            br.ReadSingle();
                        }
                        for (int k = 0; k < 4; k++)
                        {
                            stream.Position += 4;
                        }

                        submeshTextureInfo.ScaleU   = br.ReadSingle();
                        submeshTextureInfo.ScaleV   = br.ReadSingle();
                        submeshTextureInfo.ShiftU   = br.ReadSingle();
                        submeshTextureInfo.ShiftV   = br.ReadSingle();
                        submeshTextureInfo.Rotation = br.ReadSingle();

                        if (faceIsHidden)
                        {
                            submeshTextureInfo.TextureName = "tooltextures/remove_face";
                        }
                        textures.Add(submeshTextureInfo);
                    }

                    if (faces.Any())
                    {
                        Solid newSolid = new Solid(map.IDGenerator.GetNextObjectID());
                        foreach (int key in faces.Keys)
                        {
                            foreach (Face face in faces[key])
                            {
                                face.Parent = newSolid;
                                newSolid.Faces.Add(face);
                            }
                        }
                        newSolid.Colour = Colour.GetRandomBrushColour();
                        newSolid.UpdateBoundingBox();

                        MapObject parent = map.WorldSpawn;

                        newSolid.SetParent(parent);

                        newSolid.Transform(new UnitScale(Coordinate.One, newSolid.BoundingBox.Center), TransformFlags.None);
                        newSolid.Transform(new UnitScale(new Coordinate(
                                                             (decimal)xScale / newSolid.BoundingBox.Width,
                                                             (decimal)yScale / newSolid.BoundingBox.Length,
                                                             (decimal)zScale / newSolid.BoundingBox.Height), Coordinate.Zero), TransformFlags.None);
                        newSolid.UpdateBoundingBox();
                        newSolid.Transform(new UnitTranslate(new Coordinate(
                                                                 (decimal)xTranslate,
                                                                 (decimal)yTranslate,
                                                                 (decimal)zTranslate)), TransformFlags.None);
                        newSolid.UpdateBoundingBox();

                        foreach (int key in faces.Keys)
                        {
                            foreach (Face face in faces[key])
                            {
                                face.Texture.Name = textures[key].TextureName;
                                face.AlignTextureToWorld();
                                face.Texture.XScale = (decimal)textures[key].ScaleU * 0.25m;
                                face.Texture.YScale = (decimal)textures[key].ScaleV * 0.25m;
                                face.Texture.XShift = (decimal)textures[key].ShiftU;
                                face.Texture.YShift = (decimal)textures[key].ShiftV;
                                face.SetTextureRotation((decimal)textures[key].Rotation);
                            }
                        }
                    }
                }
                else
                {
                    int entitySubType = (int)br.ReadSingle();

                    for (int j = 1; j < 2; j++)
                    {
                        stream.Position += 4;
                    }
                    float xTranslate = br.ReadSingle();
                    float zTranslate = br.ReadSingle();
                    float yTranslate = br.ReadSingle();
                    float xScale     = br.ReadSingle();
                    float zScale     = br.ReadSingle();
                    float yScale     = br.ReadSingle();
                    if (Math.Abs(entitySubType - 3.0f) < 0.01f)
                    {
                        for (int j = 8; j < 35; j++)
                        {
                            stream.Position += 4;
                        }
                        string entityName    = br.ReadLine();
                        string entityIcon    = br.ReadLine();
                        int    propertyCount = (int)br.ReadSingle() + 1;
                        Dictionary <string, string> properties = new Dictionary <string, string>();
                        for (int j = 0; j < propertyCount; j++)
                        {
                            string propertyName  = br.ReadLine().ToLowerInvariant();
                            string propertyValue = br.ReadLine();
                            properties.Add(propertyName, propertyValue);
                        }

                        Entity entity = new Entity(map.IDGenerator.GetNextObjectID());
                        entity.Colour = Colour.GetDefaultEntityColour();
                        Property newProperty = null;
                        switch (entityName.ToLowerInvariant())
                        {
                        case "pointlight":
                            entity.ClassName       = "light";
                            entity.EntityData.Name = "light";

                            newProperty       = new Property();
                            newProperty.Key   = "range";
                            newProperty.Value = properties["range"];
                            entity.EntityData.Properties.Add(newProperty);

                            newProperty       = new Property();
                            newProperty.Key   = "color";
                            newProperty.Value = properties["color"].Replace(',', ' ').Trim();
                            entity.EntityData.Properties.Add(newProperty);
                            break;

                        case "spotlight":
                            entity.ClassName       = "spotlight";
                            entity.EntityData.Name = "spotlight";

                            newProperty       = new Property();
                            newProperty.Key   = "range";
                            newProperty.Value = properties["range"];
                            entity.EntityData.Properties.Add(newProperty);

                            newProperty       = new Property();
                            newProperty.Key   = "color";
                            newProperty.Value = properties["color"].Replace(',', ' ').Trim();
                            entity.EntityData.Properties.Add(newProperty);

                            newProperty       = new Property();
                            newProperty.Key   = "innerconeangle";
                            newProperty.Value = "45";
                            if (decimal.TryParse(properties["innerang"], out decimal innerAngle))
                            {
                                newProperty.Value = (innerAngle * 0.5m).ToString();
                            }
                            entity.EntityData.Properties.Add(newProperty);

                            newProperty       = new Property();
                            newProperty.Key   = "outerconeangle";
                            newProperty.Value = "90";
                            if (decimal.TryParse(properties["outerang"], out decimal outerAngle))
                            {
                                newProperty.Value = (outerAngle * 0.5m).ToString();
                            }
                            entity.EntityData.Properties.Add(newProperty);

                            newProperty       = new Property();
                            newProperty.Key   = "angles";
                            newProperty.Value = "0 0 0";
                            string[] dirParts = properties["direction"].Split(',');
                            if (decimal.TryParse(dirParts[0], out decimal dirX) &&
                                decimal.TryParse(dirParts[1], out decimal dirY) &&
                                decimal.TryParse(dirParts[2], out decimal dirZ))
                            {
                                Coordinate dir   = new Coordinate(dirX, dirY, dirZ).Normalise();
                                decimal    pitch = DMath.RadiansToDegrees(DMath.Asin(-dir.Y));
                                dir.Y = 0;
                                decimal yaw = 0m;
                                if (dir.LengthSquared() > 0.01m)
                                {
                                    dir = dir.Normalise();
                                    yaw = DMath.RadiansToDegrees(DMath.Atan2(-dir.X, dir.Z));
                                }

                                newProperty.Value = $"{pitch} {yaw} 0";
                            }
                            entity.EntityData.Properties.Add(newProperty);
                            break;

                        default:
                            entity.ClassName       = entityName;
                            entity.EntityData.Name = entityName;

                            foreach (var key in properties.Keys)
                            {
                                newProperty       = new Property();
                                newProperty.Key   = key;
                                newProperty.Value = properties[key];
                                entity.EntityData.Properties.Add(newProperty);
                            }
                            break;
                        }

                        entity.Origin = new Coordinate((decimal)xTranslate, (decimal)yTranslate, (decimal)zTranslate);
                        entity.SetParent(map.WorldSpawn);
                    }
                    else if (Math.Abs(entitySubType - 2.0f) < 0.01f)
                    {
                        if (models == null)
                        {
                            models = LoadAllModels(modelDirs);
                        }
                        ModelReference model          = null;
                        Coordinate     angles         = null;
                        Coordinate     scale          = null;
                        long           returnPosition = stream.Position;
                        for (int j = 0; j < meshCount; j++)
                        {
                            stream.Position = memblockLocations[j];

                            UInt32 memblockSize = br.ReadUInt32();
                            UInt32 dwFVF        = br.ReadUInt32();
                            UInt32 dwFVFSize    = br.ReadUInt32();
                            UInt32 dwVertMax    = br.ReadUInt32();

                            for (int k = 0; k < models.Count; k++)
                            {
                                DataStructures.Models.Mesh currMesh = models[k].Model.BodyParts[0].Meshes.Values.First()[0];

                                if (dwVertMax == currMesh.Vertices.Count)
                                {
                                    List <Pair <Coordinate, Coordinate> > points = new List <Pair <Coordinate, Coordinate> >();
                                    List <Coordinate> loadedPoints = new List <Coordinate>();
                                    Coordinate        loadedCenter = new Coordinate(0, 0, 0);
                                    Coordinate        knownCenter  = new Coordinate(0, 0, 0);
                                    for (int l = 0; l < dwVertMax; l++)
                                    {
                                        float      x     = br.ReadSingle();
                                        float      z     = br.ReadSingle();
                                        float      y     = br.ReadSingle();
                                        Coordinate point = new Coordinate((decimal)x, (decimal)y, (decimal)z);
                                        loadedPoints.Add(point);
                                        loadedCenter += point;
                                        knownCenter  += new Coordinate(currMesh.Vertices[l].Location);
                                        for (int m = 12; m < dwFVFSize; m += 4)
                                        {
                                            stream.Position += 4;
                                        }

                                        if (points.Count < 3)
                                        {
                                            int        nativeIndex = (l / 3) * 3 + ((l % 3) + 1) % 3;
                                            Coordinate vertexLoc   = new Coordinate(currMesh.Vertices[nativeIndex].Location);
                                            if (!points.Any(p => Math.Abs(p.Item1.Normalise().Dot(vertexLoc.Normalise())) > 0.95m))
                                            {
                                                points.Add(new Pair <Coordinate, Coordinate>(vertexLoc, point));
                                            }
                                        }
                                    }

                                    loadedCenter /= dwVertMax;
                                    knownCenter  /= dwVertMax;

                                    if (points.Count >= 3)
                                    {
                                        model = models[k];

                                        for (int l = 0; l < 3; l++)
                                        {
                                            points[l].Item1 -= knownCenter; points[l].Item1 = points[l].Item1.Normalise();
                                            points[l].Item2 -= loadedCenter; points[l].Item2 = points[l].Item2.Normalise();
                                        }

                                        points[2].Item1 = points[0].Item1.Cross(points[1].Item1).Normalise();
                                        points[2].Item2 = points[0].Item2.Cross(points[1].Item2).Normalise();

                                        points[1].Item1 = points[0].Item1.Cross(points[2].Item1).Normalise();
                                        points[1].Item2 = points[0].Item2.Cross(points[2].Item2).Normalise();

                                        decimal dotX0 = Coordinate.UnitX.Dot(points[0].Item1);
                                        decimal dotX1 = Coordinate.UnitX.Dot(points[1].Item1);
                                        decimal dotX2 = Coordinate.UnitX.Dot(points[2].Item1);

                                        decimal dotY0 = Coordinate.UnitY.Dot(points[0].Item1);
                                        decimal dotY1 = Coordinate.UnitY.Dot(points[1].Item1);
                                        decimal dotY2 = Coordinate.UnitY.Dot(points[2].Item1);

                                        decimal dotZ0 = Coordinate.UnitZ.Dot(points[0].Item1);
                                        decimal dotZ1 = Coordinate.UnitZ.Dot(points[1].Item1);
                                        decimal dotZ2 = Coordinate.UnitZ.Dot(points[2].Item1);

                                        Coordinate newX = (dotX0 * points[0].Item2 + dotX1 * points[1].Item2 + dotX2 * points[2].Item2);
                                        Coordinate newY = (dotY0 * points[0].Item2 + dotY1 * points[1].Item2 + dotY2 * points[2].Item2);
                                        Coordinate newZ = (dotZ0 * points[0].Item2 + dotZ1 * points[1].Item2 + dotZ2 * points[2].Item2);

                                        Coordinate unTransformedMin = new Coordinate(
                                            loadedPoints.Select(p => p.X).Min(),
                                            loadedPoints.Select(p => p.Y).Min(),
                                            loadedPoints.Select(p => p.Z).Min()
                                            );

                                        Coordinate unTransformedBounds = new Coordinate(
                                            loadedPoints.Select(p => p.X).Max(),
                                            loadedPoints.Select(p => p.Y).Max(),
                                            loadedPoints.Select(p => p.Z).Max()) - unTransformedMin;

                                        Coordinate propScale(Coordinate p)
                                        {
                                            Coordinate retVal = p.Clone();

                                            retVal.X *= (decimal)xScale / unTransformedBounds.X;
                                            retVal.Y *= (decimal)yScale / unTransformedBounds.Y;
                                            retVal.Z *= (decimal)zScale / unTransformedBounds.Z;
                                            return(retVal);
                                        }

                                        Coordinate centerDiff = propScale(loadedCenter - knownCenter);

                                        xTranslate += (float)centerDiff.X;
                                        yTranslate += (float)centerDiff.Y;
                                        zTranslate += (float)centerDiff.Z;

                                        Coordinate newBounds = new Coordinate(
                                            loadedPoints.Select(p => propScale(p).Dot(newX)).Max() - loadedPoints.Select(p => propScale(p).Dot(newX)).Min(),
                                            loadedPoints.Select(p => propScale(p).Dot(newY)).Max() - loadedPoints.Select(p => propScale(p).Dot(newY)).Min(),
                                            loadedPoints.Select(p => propScale(p).Dot(newZ)).Max() - loadedPoints.Select(p => propScale(p).Dot(newZ)).Min());

                                        Coordinate newBounds2 = new Coordinate(
                                            loadedPoints.Select(p => p.Dot(newX)).Max() - loadedPoints.Select(p => p.Dot(newX)).Min(),
                                            loadedPoints.Select(p => p.Dot(newY)).Max() - loadedPoints.Select(p => p.Dot(newY)).Min(),
                                            loadedPoints.Select(p => p.Dot(newZ)).Max() - loadedPoints.Select(p => p.Dot(newZ)).Min());

                                        scale = new Coordinate(newBounds.X / newBounds2.X, newBounds.Z / newBounds2.Z, newBounds.Y / newBounds2.Y);

                                        angles = Entity.ToEuler(newX, newY, newZ);

                                        break;
                                    }
                                }
                            }
                        }
                        stream.Position = returnPosition;
                        for (int j = 8; j < 24; j++)
                        {
                            stream.Position += 4;
                        }
                        int materialCount = (int)br.ReadSingle() + 1;
                        for (int j = 0; j < materialCount; j++)
                        {
                            string materialName = br.ReadLine();
                            for (int k = 0; k < 10; k++)
                            {
                                stream.Position += 4;
                            }
                        }

                        Entity entity = new Entity(map.IDGenerator.GetNextObjectID());
                        entity.ClassName       = "model";
                        entity.EntityData.Name = "model";
                        entity.Colour          = Colour.GetDefaultEntityColour();

                        Property newProperty;

                        if (model != null)
                        {
                            newProperty       = new Property();
                            newProperty.Key   = "file";
                            newProperty.Value = System.IO.Path.GetFileNameWithoutExtension(model.Path);
                            entity.EntityData.Properties.Add(newProperty);

                            if (angles != null)
                            {
                                newProperty       = new Property();
                                newProperty.Key   = "angles";
                                newProperty.Value = angles.ToDataString();
                                entity.EntityData.Properties.Add(newProperty);
                            }

                            if (scale != null)
                            {
                                newProperty       = new Property();
                                newProperty.Key   = "scale";
                                newProperty.Value = scale.ToDataString();
                                entity.EntityData.Properties.Add(newProperty);
                            }
                        }

                        entity.Origin = new Coordinate((decimal)xTranslate, (decimal)yTranslate, (decimal)zTranslate);
                        entity.SetParent(map.WorldSpawn);
                    }
                }
            }

            if (models != null)
            {
                models.ForEach(m => ModelProvider.DeleteModelReference(m));
            }

            return(map);
        }