Ejemplo n.º 1
0
        private void CalculateTwoSidedLowerUV(SectorPlane floor, SectorPlane ceiling,
                                              ref Vector2 start, ref Vector2 end)
        {
            float   lineLength   = wall.Line.Segment.Length();
            int     height       = ceiling.Height - floor.Height;
            Vector2 invDimension = texture.InverseDimension;
            Vector2 spanUV       = new Vector2(lineLength, height) * invDimension;
            Vector2 offsetUV     = wall.Side.Offset.Float() * invDimension;

            // If it's upper, draw from the top of the ceiling down.
            if (wall.Line.Unpegged.HasUpper())
            {
                // Remember that this draws from the very top, so we need to
                // know the sector height that will act as the top. Drawing the
                // other pieces
                float maxHeight = wall.Side.Sector.Ceiling.Height;

                // We need to find the V coordinates from the top to do these
                // correctly.
                float topV    = (maxHeight - ceiling.Height) * invDimension.y;
                float bottomV = (maxHeight - floor.Height) * invDimension.y;

                start = new Vector2(offsetUV.x, topV + offsetUV.y);
                end   = new Vector2(offsetUV.x + spanUV.x, bottomV + offsetUV.y);
            }
            else
            {
                start = offsetUV;
                end   = offsetUV + spanUV;
            }
        }
Ejemplo n.º 2
0
        private static (Vector3[] vertices, Vector2[] uvCoords) CalculateVertices(SectorPlane plane,
                                                                                  List <Seg2F> edges, Texture texture)
        {
            int vertexCount = edges.Count;

            Vector3[] vertices = new Vector3[vertexCount];
            Vector2[] uvCoords = new Vector2[vertexCount];

            for (int i = 0; i < vertexCount; i++)
            {
                Vector2 vertex = edges[i].Start.UnityFloat();
                vertices[i] = new Vector3(vertex.x, plane.Height, vertex.y).MapUnit();
                uvCoords[i] = vertex * texture.InverseDimension;
            }

            // If it's a ceiling, we have to reverse the triangle fan to make
            // the facing side visible.
            if (plane.IsCeiling)
            {
                Array.Reverse(vertices, 0, vertices.Length);
                Array.Reverse(uvCoords, 0, uvCoords.Length);
            }

            return(vertices, uvCoords);
        }
Ejemplo n.º 3
0
        private void UpdateEnabledStatus(SectorPlane floor, SectorPlane ceiling)
        {
            if (wall.IsTwoSidedNoMiddle)
            {
                Disable();
                isDisabled = true;
                return;
            }

            // We do it this way just in case enabling/disabling ends up being
            // a non-cheap operation.
            if (floor.Height <= ceiling.Height)
            {
                if (isDisabled)
                {
                    Enable();
                    isDisabled = false;
                }
            }
            else
            {
                if (!isDisabled)
                {
                    Disable();
                    isDisabled = true;
                }
            }
        }
Ejemplo n.º 4
0
        private static Color[] CalculateColors(SectorPlane sectorPlane, int vertexCount)
        {
            float lightLevel = sectorPlane.LightLevelNormalized;
            Color color      = new Color(lightLevel, lightLevel, lightLevel, 1.0f);

            return(Arrays.Create(vertexCount, color));
        }
Ejemplo n.º 5
0
 public SubsectorMeshComponents(SubsectorPlane plane, SectorPlane sectorPlane,
                                List <Seg2F> edges, GameObject gameObject)
 {
     subsectorPlane = plane;
     texture        = TextureManager.Texture(plane.SectorPlane.TextureName, ResourceNamespace.Flats);
     Mesh           = CreateMesh(sectorPlane, edges, texture);
     Filter         = CreateFilter(gameObject);
     Renderer       = CreateRenderer(gameObject);
     Collider       = CreateCollider(gameObject, edges);
 }
Ejemplo n.º 6
0
        private void CalculateTwoSidedMiddleUV(SectorPlane floor, SectorPlane ceiling,
                                               Vector3[] vertices, ref Vector2 start, ref Vector2 end)
        {
            // TODO: Should probably turn this into a data structure to avoid these cryptic references.
            float height     = vertices[2].y - vertices[0].y;
            float lineLength = wall.Line.Segment.Length();

            Vector2 invDimension = texture.InverseDimension;
            Vector2 spanUV       = new Vector2(lineLength, height) * invDimension;
            Vector2 offsetUV     = wall.Side.Offset.Float() * invDimension;

            // TODO: Draw it to the proper clipped spot.
            start = new Vector2(offsetUV.x, 0);
            end   = new Vector2(offsetUV.x + spanUV.x, 1);
        }
Ejemplo n.º 7
0
        public SubsectorPlane(int index, SectorPlane sectorPlane, List <Seg2F> edges)
        {
            Debug.Assert(edges.Count >= 3, $"Two or less lines is not a polygon (subsector plane {index})");

            string facingText = sectorPlane.IsCeiling ? "Ceiling" : "Floor";

            Index          = index;
            SectorPlane    = sectorPlane;
            Edges          = edges.ToList();
            gameObject     = new GameObject($"Subsector {index} (Sector {sectorPlane.Sector.Index} Plane {sectorPlane.Index} {facingText})");
            MeshComponents = new SubsectorMeshComponents(this, sectorPlane, edges, gameObject);
            collisionInfo  = CollisionInfo.CreateOn(gameObject, this);

            sectorPlane.SubsectorPlanes.Add(this);
        }
Ejemplo n.º 8
0
        private static Mesh CreateMesh(SectorPlane sectorPlane, List <Seg2F> edges, Texture texture)
        {
            (Vector3[] vertices, Vector2[] uvCoords) = CalculateVertices(sectorPlane, edges, texture);
            int[]     indices = CalculateIndices(vertices.Length);
            Vector3[] normals = CalculateNormals(sectorPlane, vertices.Length);
            Color[]   colors  = CalculateColors(sectorPlane, vertices.Length);

            return(new Mesh
            {
                vertices = vertices,
                triangles = indices,
                normals = normals,
                uv = uvCoords,
                colors = colors
            });
        }
Ejemplo n.º 9
0
        private Vector3[] CalculateVertices(SectorPlane floor, SectorPlane ceiling)
        {
            float top    = ceiling.Height;
            float bottom = floor.Height;
            Vec2F start  = wall.Line.Segment.Start;
            Vec2F end    = wall.Line.Segment.End;

            if (wall.OnBackSide)
            {
                (start, end) = (end, start);
            }

            if (wall.Section == WallSection.Middle && wall.Line.TwoSided)
            {
                float imageHeight = texture.Height;
                float texTop      = top;
                float texBottom   = bottom;

                // Draws from the top down, unless it's lower unpegged.
                if (wall.Line.Unpegged.HasLower())
                {
                    texTop = texBottom + imageHeight;
                }
                else
                {
                    texBottom = texTop - imageHeight;
                }

                texTop    += wall.Side.Offset.Y;
                texBottom += wall.Side.Offset.Y;

                // Now we clip it to the gap that exists.
                top    = Math.Min(top, texTop);
                bottom = Math.Max(bottom, texBottom);
            }

            return(new[]
            {
                new Vector3(start.X, bottom, start.Y).MapUnit(),
                new Vector3(end.X, bottom, end.Y).MapUnit(),
                new Vector3(start.X, top, start.Y).MapUnit(),
                new Vector3(end.X, top, end.Y).MapUnit(),
            });
        }
Ejemplo n.º 10
0
        private void CalculateTwoSidedUpperUV(SectorPlane floor, SectorPlane ceiling,
                                              ref Vector2 start, ref Vector2 end)
        {
            float   lineLength   = wall.Line.Segment.Length();
            int     height       = ceiling.Height - floor.Height;
            Vector2 invDimension = texture.InverseDimension;
            Vector2 spanUV       = new Vector2(lineLength, height) * invDimension;
            Vector2 offsetUV     = wall.Side.Offset.Float() * invDimension;

            // If it's upper, draw it from the top down.
            if (wall.Line.Unpegged.HasUpper())
            {
                start = offsetUV;
                end   = offsetUV + spanUV;
            }
            else
            {
                end   = new Vector2(spanUV.x + offsetUV.x, 1.0f - offsetUV.y);
                start = new Vector2(offsetUV.x, end.y - spanUV.y);
            }
        }
Ejemplo n.º 11
0
        private Vector2[] CalculateUVCoordinates(SectorPlane floor, SectorPlane ceiling,
                                                 Vector3[] vertices)
        {
            Vector2 start = new Vector2(0, 0);
            Vector2 end   = new Vector2(1, 1);

            // An important note for all of the following functions:
            // Remember that the texture was uploaded such that the
            // 0.0 -> 1.0 coordinates look like:
            //
            // (0.0, 0.0)      (1.0, 0.0)
            //         S--------o
            //         |  Top   |      S = start
            //         |        |      E = end
            //         |        |
            //         |        |
            //         | Bottom |
            //         o--------E
            // (0.0, 1.0)      (1.0, 1.0)
            //
            // This means when we are drawing from the bottom up, we want to
            // start out at the bottom UV and subtract the X/Y span and offsets
            // to go upwards. Likewise if we are drawing from the top down, we
            // want to start at the top two coordinates and add the span and
            // offset to go down.
            // In short, the coordinate system looks exactly like the image
            // origin system.
            switch (wall.Section)
            {
            case WallSection.Lower:
                CalculateTwoSidedLowerUV(floor, ceiling, ref start, ref end);
                break;

            case WallSection.Middle:
                if (wall.Line.OneSided)
                {
                    CalculateOneSidedMiddleUV(floor, ceiling, ref start, ref end);
                }
                else
                {
                    CalculateTwoSidedMiddleUV(floor, ceiling, vertices, ref start, ref end);
                }
                break;

            case WallSection.Upper:
                CalculateTwoSidedUpperUV(floor, ceiling, ref start, ref end);
                break;

            default:
                throw new Exception($"Unexpected wall section for UV calculations: {wall.Section}");
            }

            // This follows easily from the comment/ASCII-art above, along with
            // the vertex locations from the class documentation.
            return(new[]
            {
                new Vector2(start.x, end.y),
                new Vector2(end.x, end.y),
                new Vector2(start.x, start.y),
                new Vector2(end.x, start.y)
            });
        }
Ejemplo n.º 12
0
        private static Vector3[] CalculateNormals(SectorPlane sectorPlane, int vertexCount)
        {
            Vector3 normal = sectorPlane.IsCeiling ? Vector3.down : Vector3.up;

            return(Arrays.Create(vertexCount, normal));
        }