/// <summary>
        /// Returns ready to display render information for a sidepart of this wall.
        /// Note: Z component is the height.
        /// </summary>
        /// <param name="PartType">Which part (upper, middle, lower)</param>
        /// <param name="IsLeftSide">Left or Right side</param>
        /// <param name="TexWidth">Texture width</param>
        /// <param name="TexHeight">Texture height</param>
        /// <param name="TexShrink">Texture shrink</param>
        /// <param name="Scale">Additional scale for vertices</param>
        /// <returns></returns>
        public VertexData GetVertexData(WallPartType PartType, bool IsLeftSide, int TexWidth, int TexHeight, int TexShrink, Real Scale = 1.0f)
        {
            VertexData RI = new VertexData();
            bool drawTopDown = true;
            RooSideDefFlags flags;
            int xoffset = 0;
            int yoffset = 0;

            // fill vars based on left or right side
            if (!IsLeftSide)
            {
                RI.P0.X = P1.X;
                RI.P3.X = P2.X;
                RI.P1.X = P1.X;
                RI.P2.X = P2.X;

                RI.P0.Y = P1.Y;
                RI.P3.Y = P2.Y;
                RI.P1.Y = P1.Y;
                RI.P2.Y = P2.Y;

                flags = RightSide.Flags;
                xoffset = RightXOffset;
                yoffset = RightYOffset;

                switch (PartType)
                {
                    case WallPartType.Upper:
                        RI.P0.Z = z3;
                        RI.P3.Z = zz3;
                        RI.P1.Z = z2;
                        RI.P2.Z = zz2;
                        drawTopDown = !RightSide.Flags.IsAboveBottomUp;
                        break;

                    case WallPartType.Middle:
                        RI.P0.Z = z2;
                        RI.P3.Z = zz2;
                        RI.P1.Z = z1;
                        RI.P2.Z = zz1;
                        drawTopDown = RightSide.Flags.IsNormalTopDown;
                        break;

                    case WallPartType.Lower:
                        if (BowtieFlags.IsBelowPos || BowtieFlags.IsBelowNeg)
                        {
                            RI.P0.Z = z1Neg;
                            RI.P3.Z = zz1Neg;
                        }
                        else
                        {
                            RI.P0.Z = z1;
                            RI.P3.Z = zz1;
                        }

                        RI.P1.Z = z0;
                        RI.P2.Z = zz0;
                        drawTopDown = RightSide.Flags.IsBelowTopDown;
                        break;
                }
            }
            else
            {
                RI.P0.X = P2.X;
                RI.P3.X = P1.X;
                RI.P1.X = P2.X;
                RI.P2.X = P1.X;

                RI.P0.Y = P2.Y;
                RI.P3.Y = P1.Y;
                RI.P1.Y = P2.Y;
                RI.P2.Y = P1.Y;

                flags = LeftSide.Flags;
                xoffset = LeftXOffset;
                yoffset = LeftYOffset;

                switch (PartType)
                {
                    case WallPartType.Upper:
                        RI.P0.Z = zz3;
                        RI.P3.Z = z3;
                        RI.P1.Z = zz2;
                        RI.P2.Z = z2;
                        drawTopDown = !LeftSide.Flags.IsAboveBottomUp;
                        break;

                    case WallPartType.Middle:
                        RI.P0.Z = zz2;
                        RI.P3.Z = z2;
                        RI.P1.Z = zz1;
                        RI.P2.Z = z1;
                        drawTopDown = LeftSide.Flags.IsNormalTopDown;
                        break;

                    case WallPartType.Lower:
                        RI.P0.Z = zz1;
                        RI.P3.Z = z1;
                        RI.P1.Z = zz0;
                        RI.P2.Z = z0;
                        drawTopDown = LeftSide.Flags.IsBelowTopDown;
                        break;
                }
            }

            // scales
            Real invWidth = 1.0f / (Real)TexWidth;
            Real invHeight = 1.0f / (Real)TexHeight;
            Real invWidthFudge = 1.0f / (Real)(TexWidth << 4);
            Real invHeightFudge = 1.0f / (Real)(TexHeight << 4);

            // Start with UV calculation, see d3drender.c ---
            Real u1 = (Real)xoffset * (Real)TexShrink * invHeight;
            Real u2 = u1 + (ClientLength * (Real)TexShrink * invHeight);

            // set U
            RI.UV0.X = u1;
            RI.UV1.X = u1;
            RI.UV3.X = u2;
            RI.UV2.X = u2;

            // calculate V
            int bottom, top;
            if (!drawTopDown)
            {
                if (RI.P1.Z == RI.P2.Z)
                    bottom = (int)RI.P1.Z;
                else
                {
                    bottom = (int)MathUtil.Min(RI.P1.Z, RI.P2.Z);
                    bottom = bottom & ~(GeometryConstants.FINENESS - 1);
                }

                if (RI.P0.Z == RI.P3.Z)
                    top = (int)RI.P0.Z;
                else
                {
                    top = (int)MathUtil.Max(RI.P0.Z, RI.P3.Z);
                    top = (top + GeometryConstants.FINENESS - 1) & ~(GeometryConstants.FINENESS - 1);
                }

                if (RI.P1.Z == RI.P2.Z)
                {
                    RI.UV1.Y = 1.0f - ((Real)yoffset * (Real)TexShrink * invWidth);
                    RI.UV2.Y = 1.0f - ((Real)yoffset * (Real)TexShrink * invWidth);
                }
                else
                {
                    RI.UV1.Y = 1.0f - ((Real)yoffset * (Real)TexShrink * invWidth);
                    RI.UV2.Y = 1.0f - ((Real)yoffset * (Real)TexShrink * invWidth);
                    RI.UV1.Y -= ((Real)RI.P1.Z - bottom) * (Real)TexShrink * invWidthFudge;
                    RI.UV2.Y -= ((Real)RI.P2.Z - bottom) * (Real)TexShrink * invWidthFudge;
                }

                RI.UV0.Y = RI.UV1.Y - ((Real)(RI.P0.Z - RI.P1.Z) * (Real)TexShrink * invWidthFudge);
                RI.UV3.Y = RI.UV2.Y - ((Real)(RI.P3.Z - RI.P2.Z) * (Real)TexShrink * invWidthFudge);
            }

            // else, need to place tex origin at top left
            else
            {
                if (RI.P0.Z == RI.P3.Z)
                    top = (int)RI.P0.Z;
                else
                {
                    top = (int)MathUtil.Max(RI.P0.Z, RI.P3.Z);
                    top = (top + GeometryConstants.FINENESS - 1) & ~(GeometryConstants.FINENESS - 1);
                }

                if (RI.P1.Z == RI.P2.Z)
                    bottom = (int)RI.P1.Z;
                else
                {
                    bottom = (int)MathUtil.Min(RI.P1.Z, RI.P2.Z);
                    bottom = bottom & ~(GeometryConstants.FINENESS - 1);
                }

                if (RI.P0.Z == RI.P3.Z)
                {
                    RI.UV0.Y = 0.0f;
                    RI.UV3.Y = 0.0f;
                }
                else
                {
                    RI.UV0.Y = ((Real)top - RI.P0.Z) * (Real)TexShrink * invWidthFudge;
                    RI.UV3.Y = ((Real)top - RI.P3.Z) * (Real)TexShrink * invWidthFudge;
                }

                RI.UV0.Y -= ((Real)(yoffset * TexShrink) * invWidth);
                RI.UV3.Y -= ((Real)(yoffset * TexShrink) * invWidth);

                RI.UV1.Y = RI.UV0.Y + ((RI.P0.Z - RI.P1.Z) * (Real)TexShrink * invWidthFudge);
                RI.UV2.Y = RI.UV3.Y + ((RI.P3.Z - RI.P2.Z) * (Real)TexShrink * invWidthFudge);
            }

            // backwards
            if (flags.IsBackwards)
            {
                Real temp;

                temp = RI.UV3.X;
                RI.UV3.X = RI.UV0.X;
                RI.UV0.X = temp;

                temp = RI.UV2.X;
                RI.UV2.X = RI.UV1.X;
                RI.UV1.X = temp;
            }

            // no vtile
            // seems to apply only to middle parts, at least for bottom it creates strange holes
            if (flags.IsNoVTile && PartType == WallPartType.Middle)
            {
                if (RI.UV0.Y < 0.0f)
                {
                    Real tex, wall, ratio, temp;

                    tex = RI.UV1.Y - RI.UV0.Y;
                    if (tex == 0)
                        tex = 1.0f;
                    temp = -RI.UV0.Y;
                    ratio = temp / tex;

                    wall = RI.P0.Z - RI.P1.Z;
                    temp = wall * ratio;
                    RI.P0.Z -= temp;
                    RI.UV0.Y = 0.0f;
                }
                if (RI.UV3.Y < 0.0f)
                {
                    Real tex, wall, ratio, temp;

                    tex = RI.UV2.Y - RI.UV3.Y;
                    if (tex == 0)
                        tex = 1.0f;
                    temp = -RI.UV3.Y;
                    ratio = temp / tex;

                    wall = RI.P3.Z - RI.P2.Z;
                    temp = wall * ratio;
                    RI.P3.Z -= temp;
                    RI.UV3.Y = 0.0f;
                }

                RI.P1.Z -= 16.0f;
                RI.P2.Z -= 16.0f;
            }

            RI.UV0.Y += 1.0f / TexWidth;
            RI.UV3.Y += 1.0f / TexWidth;
            RI.UV1.Y -= 1.0f / TexWidth;
            RI.UV2.Y -= 1.0f / TexWidth;

            // scale by user scale
            RI.P0 *= Scale;
            RI.P3 *= Scale;
            RI.P1 *= Scale;
            RI.P2 *= Scale;

            // calculate the normal
            V3 P0P1 = (RI.P1 - RI.P0);
            V3 P0P2 = (RI.P2 - RI.P0);
            RI.Normal = P0P1.CrossProduct(P0P2);
            RI.Normal.Normalize();
            RI.Normal = -RI.Normal;
            return RI;
        }
示例#2
0
        /// <summary>
        /// Returns ready to display render information for a sidepart of this wall.
        /// Note: Z component is the height.
        /// </summary>
        /// <param name="PartType">Which part (upper, middle, lower)</param>
        /// <param name="IsLeftSide">Left or Right side</param>
        /// <param name="TexWidth">Texture width</param>
        /// <param name="TexHeight">Texture height</param>
        /// <param name="TexShrink">Texture shrink</param>
        /// <param name="Scale">Additional scale for vertices</param>
        /// <returns></returns>
        public RenderInfo GetRenderInfo(WallPartType PartType, bool IsLeftSide, int TexWidth, int TexHeight, int TexShrink, Real Scale = 1.0f)
        {
            RenderInfo      RI          = new RenderInfo();
            bool            drawTopDown = true;
            RooSideDefFlags flags;
            int             xoffset = 0;
            int             yoffset = 0;

            // fill vars based on left or right side
            if (!IsLeftSide)
            {
                RI.P0.X = X1;
                RI.P3.X = X2;
                RI.P1.X = X1;
                RI.P2.X = X2;

                RI.P0.Y = Y1;
                RI.P3.Y = Y2;
                RI.P1.Y = Y1;
                RI.P2.Y = Y2;

                flags   = RightSide.Flags;
                xoffset = RightXOffset;
                yoffset = RightYOffset;

                switch (PartType)
                {
                case WallPartType.Upper:
                    RI.P0.Z     = Z3;
                    RI.P3.Z     = ZZ3;
                    RI.P1.Z     = Z2;
                    RI.P2.Z     = ZZ2;
                    drawTopDown = !RightSide.Flags.IsAboveBottomUp;
                    break;

                case WallPartType.Middle:
                    RI.P0.Z     = Z2;
                    RI.P3.Z     = ZZ2;
                    RI.P1.Z     = Z1;
                    RI.P2.Z     = ZZ1;
                    drawTopDown = RightSide.Flags.IsNormalTopDown;
                    break;

                case WallPartType.Lower:
                    RI.P0.Z     = Z1;
                    RI.P3.Z     = ZZ1;
                    RI.P1.Z     = Z0;
                    RI.P2.Z     = ZZ0;
                    drawTopDown = RightSide.Flags.IsBelowTopDown;
                    break;
                }
            }
            else
            {
                RI.P0.X = X2;
                RI.P3.X = X1;
                RI.P1.X = X2;
                RI.P2.X = X1;

                RI.P0.Y = Y2;
                RI.P3.Y = Y1;
                RI.P1.Y = Y2;
                RI.P2.Y = Y1;

                flags   = LeftSide.Flags;
                xoffset = LeftXOffset;
                yoffset = LeftYOffset;

                switch (PartType)
                {
                case WallPartType.Upper:
                    RI.P0.Z     = ZZ3;
                    RI.P3.Z     = Z3;
                    RI.P1.Z     = ZZ2;
                    RI.P2.Z     = Z2;
                    drawTopDown = !LeftSide.Flags.IsAboveBottomUp;
                    break;

                case WallPartType.Middle:
                    RI.P0.Z     = ZZ2;
                    RI.P3.Z     = Z2;
                    RI.P1.Z     = ZZ1;
                    RI.P2.Z     = Z1;
                    drawTopDown = LeftSide.Flags.IsNormalTopDown;
                    break;

                case WallPartType.Lower:
                    RI.P0.Z     = ZZ1;
                    RI.P3.Z     = Z1;
                    RI.P1.Z     = ZZ0;
                    RI.P2.Z     = Z0;
                    drawTopDown = LeftSide.Flags.IsBelowTopDown;
                    break;
                }
            }

            // scales
            Real invWidth       = 1.0f / (Real)TexWidth;
            Real invHeight      = 1.0f / (Real)TexHeight;
            Real invWidthFudge  = 1.0f / (Real)(TexWidth << 4);
            Real invHeightFudge = 1.0f / (Real)(TexHeight << 4);

            // Start with UV calculation, see d3drender.c ---
            Real u1 = (Real)xoffset * (Real)TexShrink * invHeight;
            Real u2 = u1 + ((Real)ClientLength * (Real)TexShrink * invHeight);

            // set U
            RI.UV0.X = u1;
            RI.UV1.X = u1;
            RI.UV3.X = u2;
            RI.UV2.X = u2;

            // calculate V
            int bottom, top;

            if (!drawTopDown)
            {
                if (RI.P1.Z == RI.P2.Z)
                {
                    bottom = (int)RI.P1.Z;
                }
                else
                {
                    bottom = (int)MathUtil.Min(RI.P1.Z, RI.P2.Z);
                    bottom = bottom & ~(GeometryConstants.FINENESS - 1);
                }

                if (RI.P0.Z == RI.P3.Z)
                {
                    top = (int)RI.P0.Z;
                }
                else
                {
                    top = (int)MathUtil.Max(RI.P0.Z, RI.P3.Z);
                    top = (top + GeometryConstants.FINENESS - 1) & ~(GeometryConstants.FINENESS - 1);
                }

                if (RI.P1.Z == RI.P2.Z)
                {
                    RI.UV1.Y = 1.0f - ((Real)yoffset * (Real)TexShrink * invWidth);
                    RI.UV2.Y = 1.0f - ((Real)yoffset * (Real)TexShrink * invWidth);
                }
                else
                {
                    RI.UV1.Y  = 1.0f - ((Real)yoffset * (Real)TexShrink * invWidth);
                    RI.UV2.Y  = 1.0f - ((Real)yoffset * (Real)TexShrink * invWidth);
                    RI.UV1.Y -= ((Real)RI.P1.Y - bottom) * (Real)TexShrink * invWidthFudge;
                    RI.UV2.Y -= ((Real)RI.P2.Y - bottom) * (Real)TexShrink * invWidthFudge;
                }

                RI.UV0.Y = RI.UV1.Y - ((Real)(RI.P0.Z - RI.P1.Z) * (Real)TexShrink * invWidthFudge);
                RI.UV3.Y = RI.UV2.Y - ((Real)(RI.P3.Z - RI.P2.Z) * (Real)TexShrink * invWidthFudge);
            }

            // else, need to place tex origin at top left
            else
            {
                if (RI.P0.Z == RI.P3.Z)
                {
                    top = (int)RI.P0.Z;
                }
                else
                {
                    top = (int)MathUtil.Max(RI.P0.Z, RI.P3.Z);
                    top = (top + GeometryConstants.FINENESS - 1) & ~(GeometryConstants.FINENESS - 1);
                }

                if (RI.P1.Z == RI.P2.Z)
                {
                    bottom = (int)RI.P1.Z;
                }
                else
                {
                    bottom = (int)MathUtil.Min(RI.P1.Z, RI.P2.Z);
                    bottom = bottom & ~(GeometryConstants.FINENESS - 1);
                }

                if (RI.P0.Z == RI.P3.Z)
                {
                    RI.UV0.Y = 0.0f;
                    RI.UV3.Y = 0.0f;
                }
                else
                {
                    RI.UV0.Y = ((Real)top - RI.P0.Z) * (Real)TexShrink * invWidthFudge;
                    RI.UV3.Y = ((Real)top - RI.P3.Z) * (Real)TexShrink * invWidthFudge;
                }

                RI.UV0.Y -= ((Real)(yoffset * TexShrink) * invWidth);
                RI.UV3.Y -= ((Real)(yoffset * TexShrink) * invWidth);

                RI.UV1.Y = RI.UV0.Y + ((RI.P0.Z - RI.P1.Z) * (Real)TexShrink * invWidthFudge);
                RI.UV2.Y = RI.UV3.Y + ((RI.P3.Z - RI.P2.Z) * (Real)TexShrink * invWidthFudge);
            }

            // backwards
            if (flags.IsBackwards)
            {
                Real temp;

                temp     = RI.UV3.X;
                RI.UV3.X = RI.UV0.X;
                RI.UV0.X = temp;

                temp     = RI.UV2.X;
                RI.UV2.X = RI.UV1.X;
                RI.UV1.X = temp;
            }

            // no vtile
            // seems to apply only to middle parts, at least for bottom it creates strange holes
            if (flags.IsNoVTile && PartType == WallPartType.Middle)
            {
                if (RI.UV0.Y < 0.0f)
                {
                    Real tex, wall, ratio, temp;

                    tex = RI.UV1.Y - RI.UV0.Y;
                    if (tex == 0)
                    {
                        tex = 1.0f;
                    }
                    temp  = -RI.UV0.Y;
                    ratio = temp / tex;

                    wall     = RI.P0.Z - RI.P1.Z;
                    temp     = wall * ratio;
                    RI.P0.Z -= temp;
                    RI.UV0.Y = 0.0f;
                }
                if (RI.UV3.Y < 0.0f)
                {
                    Real tex, wall, ratio, temp;

                    tex = RI.UV2.Y - RI.UV3.Y;
                    if (tex == 0)
                    {
                        tex = 1.0f;
                    }
                    temp  = -RI.UV3.Y;
                    ratio = temp / tex;

                    wall     = RI.P3.Z - RI.P2.Z;
                    temp     = wall * ratio;
                    RI.P3.Z -= temp;
                    RI.UV3.Y = 0.0f;
                }

                RI.P1.Z -= 16.0f;
                RI.P2.Z -= 16.0f;
            }

            RI.UV0.Y += 1.0f / TexWidth;
            RI.UV3.Y += 1.0f / TexWidth;
            RI.UV1.Y -= 1.0f / TexWidth;
            RI.UV2.Y -= 1.0f / TexWidth;

            // scale by user scale
            RI.P0 *= Scale;
            RI.P3 *= Scale;
            RI.P1 *= Scale;
            RI.P2 *= Scale;

            // calculate the normal
            V3 P0P1 = (RI.P1 - RI.P0);
            V3 P0P2 = (RI.P2 - RI.P0);

            RI.Normal = P0P1.CrossProduct(P0P2);
            RI.Normal.Normalize();
            RI.Normal = -RI.Normal;
            return(RI);
        }
示例#3
0
 public WallTextureChangedEventArgs(RooSideDef ChangedSide, WallPartType WallPartType)
 {
     this.ChangedSide  = ChangedSide;
     this.WallPartType = WallPartType;
 }
 public WallTextureChangedEventArgs(RooSideDef ChangedSide, WallPartType WallPartType, string OldMaterialName)
 {
     this.ChangedSide = ChangedSide;
     this.WallPartType = WallPartType;
     this.OldMaterialName = OldMaterialName;
 }
 public WallTextureChangedEventArgs(RooSideDef ChangedSide, WallPartType WallPartType, string OldMaterialName)
 {
     this.ChangedSide     = ChangedSide;
     this.WallPartType    = WallPartType;
     this.OldMaterialName = OldMaterialName;
 }