Esempio n. 1
0
        public void Calculate()
        {
            // texture orientation
            Real radangle   = MathUtil.BinaryAngleToRadian((ushort)TextureAngle);
            Real texorientx = (Real)System.Math.Cos(radangle);
            Real texorienty = (Real)System.Math.Sin(radangle);
            Real texorientz = 0;

            TextureOrientation = new V3(texorientx, texorienty, texorientz);

            // generate other endpoints from plane normal, texture origin, and texture
            //  orientation which determine the orientation of the texture's u v space
            //  in the 3d world's x, y, z space

            // plane normal
            V3 planeNormal = new V3(A, B, C);

            // first point
            // calculate z of texture origin from x, y, and plane equation
            Real z = (-A * X0 - B * Y0 - D) / C;

            P0 = new V3(X0, Y0, z);

            // cross normal with texture orientation to get vector perpendicular to texture
            //  orientation and normal = v axis direction
            V3 v2 = planeNormal.CrossProduct(TextureOrientation);

            v2.ScaleToLength(GeometryConstants.FINENESS);

            // cross normal with v axis direction vector to get vector perpendicular to v axis
            //  and normal = u axis direction vector
            V3 v1 = v2.CrossProduct(planeNormal);

            v1.ScaleToLength(GeometryConstants.FINENESS);

            // add vectors to origin to get endpoints
            P1 = P0 + v1;
            P2 = P0 + v2;
        }
Esempio n. 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);
        }