private static double GetSidedefValue(Sidedef target, VisualGeometryType targetparttype, string key, double defaultvalue)
        {
            switch (targetparttype)
            {
            case VisualGeometryType.WALL_UPPER:
                return(Math.Round(UniFields.GetFloat(target.Fields, key + "_top", defaultvalue), 3));

            case VisualGeometryType.WALL_MIDDLE:
                return(Math.Round(UniFields.GetFloat(target.Fields, key + "_mid", defaultvalue), 3));

            case VisualGeometryType.WALL_LOWER:
                return(Math.Round(UniFields.GetFloat(target.Fields, key + "_bottom", defaultvalue), 3));
            }

            return(0);
        }
        private static List <WorldVertex[]> OptimizeGeometry(WorldVertex[] verts, VisualGeometryType geotype, bool skiprectoptimization)
        {
            List <WorldVertex[]> groups = new List <WorldVertex[]>();

            // Only do optimizations for walls right now. Doing them blindly for floors/ceilings will cause problems with concave sectors with 4 corners
            if (!skiprectoptimization && verts.Length == 6 && (geotype != VisualGeometryType.CEILING && geotype != VisualGeometryType.FLOOR))            //rectangular surface
            {
                verts = new[] { verts[5], verts[2], verts[1], verts[0] };
                groups.Add(verts);
            }
            else
            {
                for (int i = 0; i < verts.Length; i += 3)
                {
                    groups.Add(new[] { verts[i + 2], verts[i + 1], verts[i] });
                }
            }

            return(groups);
        }
        private void AddProcessedSides(Sidedef s1, VisualGeometryType type1, Sidedef s2, VisualGeometryType type2)
        {
            // Add them both ways
            if (!donesides[type1].ContainsKey(s1.Index))
            {
                donesides[type1].Add(s1.Index, new Dictionary <VisualGeometryType, Dictionary <int, bool> >());
                donesides[type1][s1.Index].Add(VisualGeometryType.WALL_UPPER, new Dictionary <int, bool>());
                donesides[type1][s1.Index].Add(VisualGeometryType.WALL_MIDDLE, new Dictionary <int, bool>());
                donesides[type1][s1.Index].Add(VisualGeometryType.WALL_LOWER, new Dictionary <int, bool>());
            }
            donesides[type1][s1.Index][type2].Add(s2.Index, false);

            if (!donesides[type2].ContainsKey(s2.Index))
            {
                donesides[type2].Add(s2.Index, new Dictionary <VisualGeometryType, Dictionary <int, bool> >());
                donesides[type2][s2.Index].Add(VisualGeometryType.WALL_UPPER, new Dictionary <int, bool>());
                donesides[type2][s2.Index].Add(VisualGeometryType.WALL_MIDDLE, new Dictionary <int, bool>());
                donesides[type2][s2.Index].Add(VisualGeometryType.WALL_LOWER, new Dictionary <int, bool>());
            }
            donesides[type2][s2.Index][type1].Add(s1.Index, false);
        }
示例#4
0
        public static Rectangle GetSidedefPartSize(Sidedef side, VisualGeometryType type)
        {
            Rectangle rect = new Rectangle(0, 0, Math.Max(1, (int)Math.Round(side.Line.Length)), 0);

            switch (type)
            {
            case VisualGeometryType.WALL_LOWER:
                if (side.LowRequired())
                {
                    rect.Y      = -side.Other.Sector.FloorHeight;
                    rect.Height = side.GetLowHeight();
                }
                break;

            case VisualGeometryType.WALL_UPPER:
                if (side.HighRequired())
                {
                    rect.Y      = -side.Sector.CeilHeight;
                    rect.Height = side.GetHighHeight();
                }
                break;

            case VisualGeometryType.WALL_MIDDLE:
                if (side.MiddleRequired())
                {
                    rect.Y = -side.Sector.CeilHeight;
                }
                else if (side.Other.Sector != null)                        // Double-sided
                {
                    rect.Y = -Math.Min(side.Sector.CeilHeight, side.Other.Sector.CeilHeight);
                }
                rect.Height = side.GetMiddleHeight();
                break;

            default:
                throw new NotImplementedException("GetSidedefPartSize: got unsupported geometry type: \"" + type + "\"");
            }

            return(rect);
        }
示例#5
0
 /// <summary>
 /// This creates visual geometry that is bound to a sidedef. This geometry is only visible when the sidedef is visible. It is automatically back-face culled during rendering and automatically XY intersection tested as well as back-face culled during object picking.
 /// </summary>
 protected VisualGeometry(VisualSector vs, Sidedef sd)
 {
     this.sector       = vs;
     this.sidedef      = sd;
     this.geometrytype = VisualGeometryType.UNKNOWN;             //mxd
 }
示例#6
0
 /// <summary>
 /// This creates sector-global visual geometry. This geometry is always visible when any of the sector is visible.
 /// </summary>
 protected VisualGeometry(VisualSector vs)
 {
     this.sector       = vs;
     this.geometrytype = VisualGeometryType.UNKNOWN;             //mxd
 }
        private static int GetExpectedOffsetY(Sidedef source, Sidedef target, string texturename, int textureheight, double texturescaley, double linescaley, Rectangle partsize, out VisualGeometryType matchingparttype)
        {
            if (target.MiddleTexture == texturename &&
                partsize.IntersectsWith(BuilderModesTools.GetSidedefPartSize(target, VisualGeometryType.WALL_MIDDLE)))
            {
                matchingparttype = VisualGeometryType.WALL_MIDDLE;
                int partheight = (int)Math.Round(((target.Sector.CeilHeight - source.Sector.CeilHeight) / texturescaley) * linescaley);
                return(((int)Tools.GetSidedefMiddleOffsetY(target, target.OffsetY + GetSidedefValue(target, matchingparttype, "offsety", 0f), linescaley, false) + partheight) % textureheight);
            }

            // Only check upper and lower textures if the sidedef as an other side. See https://github.com/jewalky/UltimateDoomBuilder/issues/533
            if (target.Other != null && target.HighTexture == texturename &&
                partsize.IntersectsWith(BuilderModesTools.GetSidedefPartSize(target, VisualGeometryType.WALL_UPPER)))
            {
                matchingparttype = VisualGeometryType.WALL_UPPER;
                int partheight = (int)Math.Round(((target.Sector.CeilHeight - source.Sector.CeilHeight) / texturescaley) * linescaley);
                return(((int)Tools.GetSidedefTopOffsetY(target, target.OffsetY + GetSidedefValue(target, matchingparttype, "offsety", 0f), linescaley, false) + partheight) % textureheight);
            }

            if (target.Other != null && target.LowTexture == texturename &&
                partsize.IntersectsWith(BuilderModesTools.GetSidedefPartSize(target, VisualGeometryType.WALL_LOWER)))
            {
                matchingparttype = VisualGeometryType.WALL_LOWER;
                int partheight = (int)Math.Round(((target.Sector.CeilHeight - source.Sector.CeilHeight) / texturescaley) * linescaley);
                return(((int)Tools.GetSidedefBottomOffsetY(target, target.OffsetY + GetSidedefValue(target, matchingparttype, "offsety", 0f), linescaley, false) + partheight) % textureheight);
            }

            matchingparttype = VisualGeometryType.UNKNOWN;
            return(int.MinValue);
        }
        private void CheckAlignment(Sidedef sidedef, int offsetx, int offsety, double linescalex, double linescaley, VisualGeometryType parttype, string texturename)
        {
            ImageData texture = General.Map.Data.GetTextureImage(texturename);

            if (!texture.IsImageLoaded)
            {
                return;
            }
            Rectangle partsize = BuilderModesTools.GetSidedefPartSize(sidedef, parttype);

            double scalex = ((General.Map.Config.ScaledTextureOffsets && !texture.WorldPanning) ? texture.Scale.x : 1.0f);
            double scaley = ((General.Map.Config.ScaledTextureOffsets && !texture.WorldPanning) ? texture.Scale.y : 1.0f);

            // Move offsets to proper range
            offsetx %= texture.Width;
            if (offsetx < 0)
            {
                offsetx += texture.Width;
            }
            offsety %= texture.Height;
            if (offsety < 0)
            {
                offsety += texture.Height;
            }

            // Check if current line is aligned to other sides
            ICollection <Linedef> lines = (sidedef.IsFront ? sidedef.Line.Start.Linedefs : sidedef.Line.End.Linedefs);
            Vertex v = sidedef.IsFront ? sidedef.Line.Start : sidedef.Line.End;

            foreach (Linedef line in lines)
            {
                if (line.Index == sidedef.Line.Index)
                {
                    continue;
                }

                Sidedef target = null;
                if (line.Front != null && line.End == v)
                {
                    target = line.Front;
                }
                else if (line.Back != null && line.Start == v)
                {
                    target = line.Back;
                }

                // No target?
                if (target == null)
                {
                    continue;
                }

                // Get expected texture offsets
                VisualGeometryType targetparttype;
                int alignedY = GetExpectedOffsetY(sidedef, target, texturename, texture.Height, scaley, linescaley, partsize, out targetparttype);
                if (targetparttype == VisualGeometryType.UNKNOWN)
                {
                    continue;
                }

                // Already added?
                if (donesides[parttype].ContainsKey(sidedef.Index) && donesides[parttype][sidedef.Index][targetparttype].ContainsKey(target.Index))
                {
                    continue;
                }

                // Not aligned if scaley is not equal
                double targetscaley = GetSidedefValue(target, targetparttype, "scaley", 1.0);
                if (targetscaley != linescaley)
                {
                    SubmitResult(new ResultTexturesMisaligned(sidedef, target, texturename));
                }

                double targetscalex = GetSidedefValue(target, targetparttype, "scalex", 1.0);

                alignedY %= texture.Height;
                if (alignedY < 0)
                {
                    alignedY += texture.Height;
                }

                int alignedX = (target.OffsetX + (int)GetSidedefValue(target, targetparttype, "offsetx", 0f) + (int)Math.Round(target.Line.Length / scalex * targetscalex)) % texture.Width;
                if (alignedX < 0)
                {
                    alignedX += texture.Width;
                }

                // Submit result if target offsets don't match expected ones
                if (offsetx != alignedX || offsety != alignedY)
                {
                    SubmitResult(new ResultTexturesMisaligned(sidedef, target, texturename));
                }

                // Add to collection
                AddProcessedSides(sidedef, parttype, target, targetparttype);
            }

            // Check if other sides are aligned to current side
            lines = (sidedef.IsFront ? sidedef.Line.End.Linedefs : sidedef.Line.Start.Linedefs);
            v     = (sidedef.IsFront ? sidedef.Line.End : sidedef.Line.Start);

            foreach (Linedef line in lines)
            {
                if (line.Index == sidedef.Line.Index)
                {
                    continue;
                }

                Sidedef target = null;
                if (line.Front != null && line.Start == v)
                {
                    target = line.Front;
                }
                else if (line.Back != null && line.End == v)
                {
                    target = line.Back;
                }

                // No target or laready processed?
                if (target == null)
                {
                    continue;
                }

                // Get expected texture offsets
                VisualGeometryType targetparttype;
                int alignedY = GetExpectedOffsetY(sidedef, target, texturename, texture.Height, scaley, linescaley, partsize, out targetparttype);
                if (targetparttype == VisualGeometryType.UNKNOWN)
                {
                    continue;
                }

                // Already added?
                if (donesides[parttype].ContainsKey(sidedef.Index) && donesides[parttype][sidedef.Index][targetparttype].ContainsKey(target.Index))
                {
                    continue;
                }

                // Not aligned if scaley is not equal
                double targetscaley = GetSidedefValue(target, targetparttype, "scaley", 1.0);
                if (targetscaley != linescaley)
                {
                    SubmitResult(new ResultTexturesMisaligned(sidedef, target, texturename));
                }

                alignedY %= texture.Height;
                if (alignedY < 0)
                {
                    alignedY += texture.Height;
                }

                int alignedX = (target.OffsetX + (int)GetSidedefValue(target, targetparttype, "offsetx", 0.0) - (int)Math.Round(sidedef.Line.Length / scalex * linescalex)) % texture.Width;
                if (alignedX < 0)
                {
                    alignedX += texture.Width;
                }

                // Submit result if target offsets don't match expected ones
                if (offsetx != alignedX || offsety != alignedY)
                {
                    SubmitResult(new ResultTexturesMisaligned(sidedef, target, texturename));
                }

                // Add to collection
                AddProcessedSides(sidedef, parttype, target, targetparttype);
            }
        }
示例#9
0
        private static int GetExpectedOffsetY(Sidedef source, Sidedef target, string texturename, int textureheight, double texturescaley, double linescaley, Rectangle partsize, out VisualGeometryType matchingparttype)
        {
            if (target.MiddleTexture == texturename &&
                partsize.IntersectsWith(BuilderModesTools.GetSidedefPartSize(target, VisualGeometryType.WALL_MIDDLE)))
            {
                matchingparttype = VisualGeometryType.WALL_MIDDLE;
                int partheight = (int)Math.Round(((target.Sector.CeilHeight - source.Sector.CeilHeight) / texturescaley) * linescaley);
                return(((int)Tools.GetSidedefMiddleOffsetY(target, target.OffsetY + GetSidedefValue(target, matchingparttype, "offsety", 0f), linescaley, false) + partheight) % textureheight);
            }

            if (target.HighTexture == texturename &&
                partsize.IntersectsWith(BuilderModesTools.GetSidedefPartSize(target, VisualGeometryType.WALL_UPPER)))
            {
                matchingparttype = VisualGeometryType.WALL_UPPER;
                int partheight = (int)Math.Round(((target.Sector.CeilHeight - source.Sector.CeilHeight) / texturescaley) * linescaley);
                return(((int)Tools.GetSidedefTopOffsetY(target, target.OffsetY + GetSidedefValue(target, matchingparttype, "offsety", 0f), linescaley, false) + partheight) % textureheight);
            }

            if (target.LowTexture == texturename &&
                partsize.IntersectsWith(BuilderModesTools.GetSidedefPartSize(target, VisualGeometryType.WALL_LOWER)))
            {
                matchingparttype = VisualGeometryType.WALL_LOWER;
                int partheight = (int)Math.Round(((target.Sector.CeilHeight - source.Sector.CeilHeight) / texturescaley) * linescaley);
                return(((int)Tools.GetSidedefBottomOffsetY(target, target.OffsetY + GetSidedefValue(target, matchingparttype, "offsety", 0f), linescaley, false) + partheight) % textureheight);
            }

            matchingparttype = VisualGeometryType.UNKNOWN;
            return(int.MinValue);
        }
 private static List <WorldVertex[]> OptimizeGeometry(WorldVertex[] verts, VisualGeometryType geotype)
 {
     return(OptimizeGeometry(verts, geotype, false));
 }