Exemplo n.º 1
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);
        }
Exemplo n.º 2
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();
        }