Beispiel #1
0
        private static XElement GetVertexElement(ESOModel model, int index)
        {
            var element = new XElement("Vertex");

            element.SetAttributeValueWithDefault("Position", model.Vertices[index]);
            if (model.HasNormals)
            {
                element.SetAttributeValueWithDefault("Normal", model.Normals[index]);
            }
            if (model.HasColors)
            {
                element.SetAttributeValueWithDefault("Color", model.Colors[index].GetString(), "Transparent");
            }
            if (model.HasTexCoords)
            {
                element.SetAttributeValueWithDefault("TexCoord", model.TexCoords[index]);
            }
            if (model.HasTexCoords2)
            {
                element.SetAttributeValueWithDefault("TexCoords2", model.TexCoords2[index]);
            }
            return(element);
        }
Beispiel #2
0
        public string Generate(string path)
        {
            var models = new ESOModel[4];

            for (short x = 0; x < level.Size.Width; x++)
            {
                for (short y = 0; y < level.Size.Length; y++)
                {
                    for (short z = 0; z < level.Size.Height; z++)
                    {
                        var info = GetInformation(x, y, z);
                        if (info.Height < 0)
                        {
                            continue;
                        }
                        var theme = themes[info.Theme];
                        if (models[theme] == null)
                        {
                            models[theme] = new ESOModel(ESOModel.Flags.Normals | ESOModel.Flags.TexCoords)
                            {
                                MaterialAsset = AssetHash.Parse(Materials[theme] + ModelsNamespace)
                            }
                        }
                        ;
                        var   model = models[theme];
                        short x1 = (short)(x + 1), y1 = (short)(y + 1), z1 = (short)(z + 1);
                        float texY1 = 1 - z * 0.25F, texY = texY1 - 0.25F;
                        if (GetInformation(x, y, z1).Height < 1 && (Math.Abs(x - level.ExitPoint.X) > 1 ||
                                                                    Math.Abs(y - level.ExitPoint.Y) > 1 || z1 != level.ExitPoint.Z))
                        {
                            model.Vertices.Add(Transform(new Vec3(x, z1, y)));
                            model.Vertices.Add(Transform(new Vec3(x1, z1, y)));
                            model.Vertices.Add(Transform(new Vec3(x, z1, y1)));
                            model.Vertices.Add(Transform(new Vec3(x, z1, y1)));
                            model.Vertices.Add(Transform(new Vec3(x1, z1, y)));
                            model.Vertices.Add(Transform(new Vec3(x1, z1, y1)));
                            model.Normals.AddRange(YNormals);
                            float texX = ((x + y) & 1) == 0 ? 0.51F : 0.76F, texX1 = texX + 0.23F;
                            model.TexCoords.Add(new Vec2(texX, texY));
                            model.TexCoords.Add(new Vec2(texX1, texY));
                            model.TexCoords.Add(new Vec2(texX, texY1));
                            model.TexCoords.Add(new Vec2(texX, texY1));
                            model.TexCoords.Add(new Vec2(texX1, texY));
                            model.TexCoords.Add(new Vec2(texX1, texY1));
                        }
                        if (info.Height <= 0)
                        {
                            continue;
                        }
                        var zB = z1 - info.Height;
                        texY1 -= 0.25F * (1 - info.Height);
                        if (GetInformation(x1, y, z).Height < info.Height)
                        {
                            model.Vertices.Add(Transform(new Vec3(x1, zB, y)));
                            model.Vertices.Add(Transform(new Vec3(x1, zB, y1)));
                            model.Vertices.Add(Transform(new Vec3(x1, z1, y)));
                            model.Vertices.Add(Transform(new Vec3(x1, zB, y1)));
                            model.Vertices.Add(Transform(new Vec3(x1, z1, y1)));
                            model.Vertices.Add(Transform(new Vec3(x1, z1, y)));
                            model.Normals.AddRange(XNormals);
                            model.TexCoords.Add(new Vec2(0.49F, texY1));
                            model.TexCoords.Add(new Vec2(0.26F, texY1));
                            model.TexCoords.Add(new Vec2(0.49F, texY));
                            model.TexCoords.Add(new Vec2(0.26F, texY1));
                            model.TexCoords.Add(new Vec2(0.26F, texY));
                            model.TexCoords.Add(new Vec2(0.49F, texY));
                        }
                        if (GetInformation(x, y1, z).Height < info.Height)
                        {
                            model.Vertices.Add(Transform(new Vec3(x, zB, y1)));
                            model.Vertices.Add(Transform(new Vec3(x, z1, y1)));
                            model.Vertices.Add(Transform(new Vec3(x1, zB, y1)));
                            model.Vertices.Add(Transform(new Vec3(x, z1, y1)));
                            model.Vertices.Add(Transform(new Vec3(x1, z1, y1)));
                            model.Vertices.Add(Transform(new Vec3(x1, zB, y1)));
                            model.Normals.AddRange(ZNormals);
                            model.TexCoords.Add(new Vec2(0.01F, texY1));
                            model.TexCoords.Add(new Vec2(0.01F, texY));
                            model.TexCoords.Add(new Vec2(0.24F, texY1));
                            model.TexCoords.Add(new Vec2(0.01F, texY));
                            model.TexCoords.Add(new Vec2(0.24F, texY));
                            model.TexCoords.Add(new Vec2(0.24F, texY1));
                        }
                    }
                }
            }
            string fileName = Path.GetFileNameWithoutExtension(path) + ".rmdl", result;

            models = models.Where(model => model != null).ToArray();
            new ESO
            {
                AssetHeader = new AssetHeader(AssetUtil.EngineVersion.Version1804Edge, fileName, "models"),
                Models      = models, Header = new ESOHeader
                {
                    V01         = 1, V02 = 4096, V20 = 1, NumModels = models.Length, ScaleXYZ = 1,
                    Scale       = new Vec3(0.1F, 0.1F, 0.1F), Translate = Translates[themes[0]],
                    NodeChild   = AssetHash.Parse(ChildModels[themes[0]] + ModelsNamespace),
                    BoundingMin = Transform(new Vec3()),
                    BoundingMax = Transform(new Vec3(level.Size.Width, level.Size.Height, level.Size.Length))
                }
            }.Save(result = Path.Combine(Path.GetDirectoryName(path),
                                         AssetUtil.CrcFullName(fileName, "models") + ".eso"));
            return(result);
        }
    }
Beispiel #3
0
        public static ESO ParseEso(XElement element, string name, string nameSpace = "models")
        {
            var  scaleXyz  = element.GetAttributeValueWithDefault <float>("ScaleXYZ", 1);
            Vec3 translate = element.GetAttributeValueWithDefault <Vec3>("Translate"),
                 rotate    = element.GetAttributeValueWithDefault <Vec3>("Rotate") * ToRadian,
                 scale     = element.GetAttributeValueWithDefault("Scale", new Vec3(1, 1, 1));
            var mode       = element.GetAttributeValueWithDefault <ApplyTransformMode>("ApplyTransform");
            var matrix     = new Matrix3D();

            if (mode.HasFlag(ApplyTransformMode.MultiplicationOnly) || mode.HasFlag(ApplyTransformMode.DivisionOnly))
            {
                matrix.Scale(ConvertVector(scale));
                matrix.Scale(new Vector3D(scaleXyz, scaleXyz, scaleXyz));
                matrix.Rotate(new Quaternion(new Vector3D(1, 0, 0), rotate.X * ToDegree));
                matrix.Rotate(new Quaternion(new Vector3D(0, 1, 0), rotate.Y * ToDegree));
                matrix.Rotate(new Quaternion(new Vector3D(0, 0, 1), rotate.Z * ToDegree));
                matrix.Translate(ConvertVector(translate));
                if (mode.HasFlag(ApplyTransformMode.DivisionOnly))
                {
                    matrix.Invert();
                }
            }
            if (mode.HasFlag(ApplyTransformMode.Remove))
            {
                scaleXyz = 1;
                rotate   = translate = default(Vec3);
                scale    = new Vec3(1, 1, 1);
            }
            var modelsAutoNormals = element.GetAttributeValueWithDefault <bool>("AutoNormals");
            var models            = new List <ESOModel>();

            foreach (var e in element.ElementsCaseInsensitive("Model"))
            {
                var modelAutoNormals = e.GetAttributeValueWithDefault("AutoNormals", modelsAutoNormals);
                var triangles        = e.ElementsCaseInsensitive("Triangle").ToArray();
                var vertexCount      = triangles.Length * 3;
                var model            = new ESOModel(numVerts: vertexCount)
                {
                    MaterialAsset = e.GetAttributeValueWithDefault <AssetHash>("MaterialAsset")
                };
                foreach (var triangle in triangles)
                {
                    var autoNormals = triangle.GetAttributeValueWithDefault("AutoNormals", modelAutoNormals);
                    var normals     = new bool[3];
                    var i           = model.Vertices.Count;
                    var vertices    = triangle.ElementsCaseInsensitive("Vertex").ToArray();
                    if (vertices.Length != 3)
                    {
                        throw new FormatException(Localization.TriangleVertexCountError);
                    }
                    foreach (var vertex in vertices)
                    {
                        model.Vertices.Add(ConvertFromVertex(matrix.Transform
                                                                 (ConvertVertex(vertex.GetAttributeValueWithDefault <Vec3>("Position")))));
                        if (vertex.AttributeCaseInsensitive("Normal") != null)
                        {
                            if (!model.HasNormals)
                            {
                                model.HasNormals = true;
                                model.Normals.AddRange(
                                    from j in Enumerable.Range(0, model.Vertices.Count - 1) select default(Vec3));
                            }
                            normals[model.Normals.Count - i] = true;
                        }
                        if (model.HasNormals)
                        {
                            model.Normals.Add(ConvertFromVector(matrix.Transform(
                                                                    ConvertVector(vertex.GetAttributeValueWithDefault <Vec3>("Normal")))));
                        }
                        if (!model.HasColors && vertex.AttributeCaseInsensitive("Color") != null)
                        {
                            model.HasColors = true;
                            model.Colors.AddRange(
                                from j in Enumerable.Range(0, model.Vertices.Count - 1) select Color.Transparent);
                        }
                        if (model.HasColors)
                        {
                            model.Colors.Add(Helper.Parse(vertex.GetAttributeValueWithDefault("Color", "Transparent")));
                        }
                        if (!model.HasTexCoords && vertex.AttributeCaseInsensitive("TexCoord") != null)
                        {
                            model.HasTexCoords = true;
                            model.TexCoords.AddRange(
                                from j in Enumerable.Range(0, model.Vertices.Count - 1) select default(Vec2));
                        }
                        if (model.HasTexCoords)
                        {
                            model.TexCoords.Add(vertex.GetAttributeValueWithDefault <Vec2>("TexCoord"));
                        }
                        if (!model.HasTexCoords2 && vertex.AttributeCaseInsensitive("TexCoord2") != null)
                        {
                            model.HasTexCoords2 = true;
                            model.TexCoords2.AddRange(
                                from j in Enumerable.Range(0, model.Vertices.Count - 1) select default(Vec2));
                        }
                        if (model.HasTexCoords2)
                        {
                            model.TexCoords2.Add(vertex.GetAttributeValueWithDefault <Vec2>("TexCoord2"));
                        }
                    }
                    if (!autoNormals)
                    {
                        continue;
                    }
                    model.HasNormals = true;
                    model.Normals.AddRange(from j in Enumerable.Range(0, i - model.Normals.Count) select default(Vec3));
                    var p0     = ConvertVertex(model.Vertices[i]);
                    var normal = Vector3D.CrossProduct(ConvertVertex(model.Vertices[i + 2]) - p0,
                                                       ConvertVertex(model.Vertices[i + 1]) - p0);
                    var vec3 = new Vec3((float)normal.X, (float)normal.Y, (float)normal.Z);
                    for (var j = i; j < model.Vertices.Count; j++)
                    {
                        if (!normals[j - i])
                        {
                            model.Normals[j] = vec3;
                        }
                    }
                }
                models.Add(model);
            }
            var result = new ESO
            {
                AssetHeader = new AssetHeader(AssetUtil.EngineVersion.Version1804Edge, name, nameSpace),
                Models      = models.ToArray(), Header = new ESOHeader
                {
                    V01         = element.GetAttributeValueWithDefault <int>("V01"),
                    V02         = element.GetAttributeValueWithDefault <int>("V02"),
                    NodeChild   = element.GetAttributeValueWithDefault <AssetHash>("NodeChild"),
                    NodeSibling = element.GetAttributeValueWithDefault <AssetHash>("NodeSibling"),
                    V07         = element.GetAttributeValueWithDefault <int>("V07"),
                    V08         = element.GetAttributeValueWithDefault <int>("V08"),
                    V09         = element.GetAttributeValueWithDefault <int>("V09"),
                    V21         = element.GetAttributeValueWithDefault <int>("V21"),
                    ScaleXYZ    = scaleXyz, Scale = scale, Translate = translate, Rotate = rotate,
                    NumModels   = models.Count, V20 = element.GetAttributeValueWithDefault <float>("V20")
                }
            };

            if (models.Count > 0)
            {
                result.Header.BoundingMin = ConvertFromVertex(matrix.Transform(
                                                                  ConvertVertex(element.GetAttributeValueWithDefault <Vec3>("BoundingMin"))));
                result.Header.BoundingMax = ConvertFromVertex(matrix.Transform(
                                                                  ConvertVertex(element.GetAttributeValueWithDefault <Vec3>("BoundingMax"))));
                result.Footer = new ESOFooter(element.GetAttributeValueWithDefault <float>("FooterV01"),
                                              element.GetAttributeValueWithDefault <float>("FooterV02"),
                                              element.GetAttributeValueWithDefault <int>("FooterV03"),
                                              element.GetAttributeValueWithDefault <int>("FooterV04"));
                if (Math.Abs(result.Footer.V01) > 1e-4 || Math.Abs(result.Footer.V02) > 1e-4 || result.Footer.V03 != 0 ||
                    result.Footer.V04 != 0)
                {
                    result.HasFooter = true;
                }
            }
            return(result);
        }