Exemplo n.º 1
0
        // Call to change the height
        public override void OnChangeTargetHeight(int amount)
        {
            // Only do this when not done yet in this call
            // Because we may be able to select the same 3D floor multiple times through multiple sectors
            SectorData sd = mode.GetSectorData(level.sector);

            if (!sd.CeilingChanged)
            {
                sd.CeilingChanged = true;
                base.OnChangeTargetHeight(amount);
            }
        }
Exemplo n.º 2
0
        // Constructor
        public EffectThingVertexSlope(SectorData data, List <Thing> sourcethings, bool floor) : base(data)
        {
            things     = sourcethings;
            slopefloor = floor;

            // New effect added: This sector needs an update!
            if (data.Mode.VisualSectorExists(data.Sector))
            {
                BaseVisualSector vs = (BaseVisualSector)data.Mode.GetVisualSector(data.Sector);
                vs.UpdateSectorGeometry(true);
            }
        }
Exemplo n.º 3
0
        // This makes sure we are updated with the source linedef information
        public override void Update()
        {
            SectorData sd = data.Mode.GetSectorData(linedef.Front.Sector);

            if (!sd.Updated)
            {
                sd.Update();
            }
            sd.AddUpdateSector(data.Sector, false);

            if (level == null)
            {
                level = new SectorLevel(sd.Ceiling);
                data.AddSectorLevel(level);
            }

            // Update level
            sd.Ceiling.CopyProperties(level);
            level.type = SectorLevelType.Light;
        }
Exemplo n.º 4
0
        public bool Setup(Effect3DFloor extrafloor)
        {
            Vector2D vl, vr;
            Sidedef  sourceside = extrafloor.Linedef.Front;

            this.extrafloor = extrafloor;

            int  lightvalue    = Sidedef.Fields.GetValue("light", 0);
            bool lightabsolute = Sidedef.Fields.GetValue("lightabsolute", false);

            Vector2D tscale = new Vector2D(sourceside.Fields.GetValue("scalex_mid", 1.0f),
                                           sourceside.Fields.GetValue("scaley_mid", 1.0f));
            Vector2D toffset1 = new Vector2D(Sidedef.Fields.GetValue("offsetx_mid", 0.0f),
                                             Sidedef.Fields.GetValue("offsety_mid", 0.0f));
            Vector2D toffset2 = new Vector2D(sourceside.Fields.GetValue("offsetx_mid", 0.0f),
                                             sourceside.Fields.GetValue("offsety_mid", 0.0f));

            // Left and right vertices for this sidedef
            if (Sidedef.IsFront)
            {
                vl = new Vector2D(Sidedef.Line.Start.Position.x, Sidedef.Line.Start.Position.y);
                vr = new Vector2D(Sidedef.Line.End.Position.x, Sidedef.Line.End.Position.y);
            }
            else
            {
                vl = new Vector2D(Sidedef.Line.End.Position.x, Sidedef.Line.End.Position.y);
                vr = new Vector2D(Sidedef.Line.Start.Position.x, Sidedef.Line.Start.Position.y);
            }

            // Load sector data
            SectorData sd = mode.GetSectorData(Sidedef.Sector);

            // Texture given?
            if ((sourceside.MiddleTexture.Length > 0) && (sourceside.MiddleTexture[0] != '-'))
            {
                // Load texture
                base.Texture = General.Map.Data.GetTextureImage(sourceside.LongMiddleTexture);
                if (base.Texture == null)
                {
                    base.Texture         = General.Map.Data.MissingTexture3D;
                    setuponloadedtexture = sourceside.LongMiddleTexture;
                }
                else
                {
                    if (!base.Texture.IsImageLoaded)
                    {
                        setuponloadedtexture = sourceside.LongMiddleTexture;
                    }
                }
            }
            else
            {
                // Use missing texture
                base.Texture         = General.Map.Data.MissingTexture3D;
                setuponloadedtexture = 0;
            }

            // Get texture scaled size
            Vector2D tsz = new Vector2D(base.Texture.ScaledWidth, base.Texture.ScaledHeight);

            tsz = tsz / tscale;

            // Get texture offsets
            Vector2D tof = new Vector2D(Sidedef.OffsetX, Sidedef.OffsetY);

            tof = tof + toffset1 + toffset2;
            tof = tof / tscale;
            if (General.Map.Config.ScaledTextureOffsets && !base.Texture.WorldPanning)
            {
                tof = tof * base.Texture.Scale;
            }

            // For Vavoom type 3D floors the ceiling is lower than floor and they are reversed.
            // We choose here.
            float sourcetopheight    = extrafloor.VavoomType ? sourceside.Sector.FloorHeight : sourceside.Sector.CeilHeight;
            float sourcebottomheight = extrafloor.VavoomType ? sourceside.Sector.CeilHeight : sourceside.Sector.FloorHeight;

            // Determine texture coordinates plane as they would be in normal circumstances.
            // We can then use this plane to find any texture coordinate we need.
            // The logic here is the same as in the original VisualMiddleSingle (except that
            // the values are stored in a TexturePlane)
            // NOTE: I use a small bias for the floor height, because if the difference in
            // height is 0 then the TexturePlane doesn't work!
            TexturePlane tp        = new TexturePlane();
            float        floorbias = (sourcetopheight == sourcebottomheight) ? 1.0f : 0.0f;

            tp.trb.x = tp.tlt.x + Sidedef.Line.Length;
            tp.trb.y = tp.tlt.y + (sourcetopheight - sourcebottomheight) + floorbias;

            // Apply texture offset
            tp.tlt += tof;
            tp.trb += tof;

            // Transform pixel coordinates to texture coordinates
            tp.tlt /= tsz;
            tp.trb /= tsz;

            // Left top and right bottom of the geometry that
            tp.vlt = new Vector3D(vl.x, vl.y, sourcetopheight);
            tp.vrb = new Vector3D(vr.x, vr.y, sourcebottomheight + floorbias);

            // Make the right-top coordinates
            tp.trt = new Vector2D(tp.trb.x, tp.tlt.y);
            tp.vrt = new Vector3D(tp.vrb.x, tp.vrb.y, tp.vlt.z);

            // Get ceiling and floor heights
            float fl = sd.Floor.plane.GetZ(vl);
            float fr = sd.Floor.plane.GetZ(vr);
            float cl = sd.Ceiling.plane.GetZ(vl);
            float cr = sd.Ceiling.plane.GetZ(vr);

            // Anything to see?
            if (((cl - fl) > 0.01f) || ((cr - fr) > 0.01f))
            {
                // Keep top and bottom planes for intersection testing
                top    = extrafloor.Floor.plane;
                bottom = extrafloor.Ceiling.plane;

                // Create initial polygon, which is just a quad between floor and ceiling
                WallPolygon poly = new WallPolygon();
                poly.Add(new Vector3D(vl.x, vl.y, fl));
                poly.Add(new Vector3D(vl.x, vl.y, cl));
                poly.Add(new Vector3D(vr.x, vr.y, cr));
                poly.Add(new Vector3D(vr.x, vr.y, fr));

                // Determine initial color
                int        lightlevel     = lightabsolute ? lightvalue : sd.Ceiling.brightnessbelow + lightvalue;
                PixelColor wallbrightness = PixelColor.FromInt(mode.CalculateBrightness(lightlevel));
                PixelColor wallcolor      = PixelColor.Modulate(sd.Ceiling.colorbelow, wallbrightness);
                poly.color = wallcolor.WithAlpha(255).ToInt();

                // Cut off the part above the 3D floor and below the 3D ceiling
                CropPoly(ref poly, extrafloor.Floor.plane, false);
                CropPoly(ref poly, extrafloor.Ceiling.plane, false);

                // Cut out pieces that overlap 3D floors in this sector
                List <WallPolygon> polygons = new List <WallPolygon>(1);
                polygons.Add(poly);
                foreach (Effect3DFloor ef in sd.ExtraFloors)
                {
                    // Same 3D floor and other floors that are not translucent will clip my walls
                    if ((ef.Alpha == 255) || (ef.Linedef.Front.Sector == extrafloor.Linedef.Front.Sector))
                    {
                        int num = polygons.Count;
                        for (int pi = 0; pi < num; pi++)
                        {
                            // Split by floor plane of 3D floor
                            WallPolygon p  = polygons[pi];
                            WallPolygon np = SplitPoly(ref p, ef.Ceiling.plane, true);

                            if (np.Count > 0)
                            {
                                // Split part below floor by the ceiling plane of 3D floor
                                // and keep only the part below the ceiling (front)
                                SplitPoly(ref np, ef.Floor.plane, true);

                                if (p.Count == 0)
                                {
                                    polygons[pi] = np;
                                }
                                else
                                {
                                    polygons[pi] = p;
                                    polygons.Add(np);
                                }
                            }
                            else
                            {
                                polygons[pi] = p;
                            }
                        }
                    }
                }

                // Process the polygon and create vertices
                List <WorldVertex> verts = CreatePolygonVertices(polygons, tp, sd, lightvalue, lightabsolute);
                if (verts.Count > 0)
                {
                    if (extrafloor.Alpha < 255)
                    {
                        // Apply alpha to vertices
                        byte alpha = (byte)General.Clamp(extrafloor.Alpha, 0, 255);
                        if (alpha < 255)
                        {
                            for (int i = 0; i < verts.Count; i++)
                            {
                                WorldVertex v = verts[i];
                                PixelColor  c = PixelColor.FromInt(v.c);
                                v.c      = c.WithAlpha(alpha).ToInt();
                                verts[i] = v;
                            }
                        }

                        this.RenderPass = RenderPass.Alpha;
                    }
                    else
                    {
                        this.RenderPass = RenderPass.Mask;
                    }

                    base.SetVertices(verts);
                    return(true);
                }
            }

            return(false);
        }
        // This creates vertices from a wall polygon and applies lighting
        protected List <WorldVertex> CreatePolygonVertices(List <WallPolygon> poly, TexturePlane tp, SectorData sd, int lightvalue, bool lightabsolute)
        {
            List <WallPolygon> polygons = new List <WallPolygon>(poly);
            List <WorldVertex> verts    = new List <WorldVertex>();

            // Go for all levels to build geometry
            for (int i = sd.LightLevels.Count - 1; i >= 0; i--)
            {
                SectorLevel l = sd.LightLevels[i];
                if ((l != sd.Floor) && (l != sd.Ceiling) && (l.type != SectorLevelType.Floor))
                {
                    // Go for all polygons
                    int num = polygons.Count;
                    for (int pi = 0; pi < num; pi++)
                    {
                        // Split by plane
                        WallPolygon p  = polygons[pi];
                        WallPolygon np = SplitPoly(ref p, l.plane, false);
                        if (np.Count > 0)
                        {
                            // Determine color
                            int        lightlevel     = lightabsolute ? lightvalue : l.brightnessbelow + lightvalue;
                            PixelColor wallbrightness = PixelColor.FromInt(mode.CalculateBrightness(lightlevel));
                            PixelColor wallcolor      = PixelColor.Modulate(l.colorbelow, wallbrightness);
                            np.color = wallcolor.WithAlpha(255).ToInt();

                            if (p.Count == 0)
                            {
                                polygons[pi] = np;
                            }
                            else
                            {
                                polygons[pi] = p;
                                polygons.Add(np);
                            }
                        }
                        else
                        {
                            polygons[pi] = p;
                        }
                    }
                }
            }

            // Go for all polygons to make geometry
            foreach (WallPolygon p in polygons)
            {
                // Find texture coordinates for each vertex in the polygon
                List <Vector2D> texc = new List <Vector2D>(p.Count);
                foreach (Vector3D v in p)
                {
                    texc.Add(tp.GetTextureCoordsAt(v));
                }

                // Now we create triangles from the polygon.
                // The polygon is convex and clockwise, so this is a piece of cake.
                if (p.Count >= 3)
                {
                    for (int k = 1; k < (p.Count - 1); k++)
                    {
                        verts.Add(new WorldVertex(p[0], p.color, texc[0]));
                        verts.Add(new WorldVertex(p[k], p.color, texc[k]));
                        verts.Add(new WorldVertex(p[k + 1], p.color, texc[k + 1]));
                    }
                }
            }

            return(verts);
        }
        // This creates vertices from a wall polygon and applies lighting
        protected List <WorldVertex> CreatePolygonVertices(WallPolygon poly, TexturePlane tp, SectorData sd, int lightvalue, bool lightabsolute)
        {
            List <WallPolygon> polylist = new List <WallPolygon>(1);

            polylist.Add(poly);
            return(CreatePolygonVertices(polylist, tp, sd, lightvalue, lightabsolute));
        }
Exemplo n.º 7
0
        // This makes sure we are updated with the source linedef information
        public override void Update()
        {
            ThingData td = data.Mode.GetThingData(thing);
            Thing     t  = thing;

            // Find the tagged line
            Linedef ld = null;

            foreach (Linedef l in General.Map.Map.Linedefs)
            {
                if (l.Tag == t.Args[0])
                {
                    ld = l;
                    break;
                }
            }

            if (ld != null)
            {
                if (t.Type == 9500)
                {
                    // Slope the floor from the linedef to thing
                    t.DetermineSector(data.Mode.BlockMap);
                    if (t.Sector != null)
                    {
                        Vector3D v3 = new Vector3D(t.Position.x, t.Position.y, t.Position.z + t.Sector.FloorHeight);
                        if (ld.SideOfLine(t.Position) < 0.0f)
                        {
                            Vector3D   v1 = new Vector3D(ld.Start.Position.x, ld.Start.Position.y, ld.Front.Sector.FloorHeight);
                            Vector3D   v2 = new Vector3D(ld.End.Position.x, ld.End.Position.y, ld.Front.Sector.FloorHeight);
                            SectorData sd = data.Mode.GetSectorData(ld.Front.Sector);
                            sd.AddUpdateSector(data.Sector, true);
                            if (!sd.Updated)
                            {
                                sd.Update();
                            }
                            td.AddUpdateSector(ld.Front.Sector, true);
                            sd.Floor.plane = new Plane(v1, v2, v3, true);
                        }
                        else
                        {
                            Vector3D   v1 = new Vector3D(ld.Start.Position.x, ld.Start.Position.y, ld.Back.Sector.FloorHeight);
                            Vector3D   v2 = new Vector3D(ld.End.Position.x, ld.End.Position.y, ld.Back.Sector.FloorHeight);
                            SectorData sd = data.Mode.GetSectorData(ld.Back.Sector);
                            sd.AddUpdateSector(data.Sector, true);
                            if (!sd.Updated)
                            {
                                sd.Update();
                            }
                            td.AddUpdateSector(ld.Back.Sector, true);
                            sd.Floor.plane = new Plane(v2, v1, v3, true);
                        }
                    }
                }
                else if (t.Type == 9501)
                {
                    // Slope the ceiling from the linedef to thing
                    t.DetermineSector(data.Mode.BlockMap);
                    if (t.Sector != null)
                    {
                        td.AddUpdateSector(t.Sector, true);
                        Vector3D v3 = new Vector3D(t.Position.x, t.Position.y, t.Position.z + t.Sector.CeilHeight);
                        if (ld.SideOfLine(t.Position) < 0.0f)
                        {
                            Vector3D   v1 = new Vector3D(ld.Start.Position.x, ld.Start.Position.y, ld.Front.Sector.CeilHeight);
                            Vector3D   v2 = new Vector3D(ld.End.Position.x, ld.End.Position.y, ld.Front.Sector.CeilHeight);
                            SectorData sd = data.Mode.GetSectorData(ld.Front.Sector);
                            sd.AddUpdateSector(data.Sector, true);
                            td.AddUpdateSector(ld.Front.Sector, true);
                            if (!sd.Updated)
                            {
                                sd.Update();
                            }
                            sd.Ceiling.plane = new Plane(v1, v2, v3, false);
                        }
                        else
                        {
                            Vector3D   v1 = new Vector3D(ld.Start.Position.x, ld.Start.Position.y, ld.Back.Sector.CeilHeight);
                            Vector3D   v2 = new Vector3D(ld.End.Position.x, ld.End.Position.y, ld.Back.Sector.CeilHeight);
                            SectorData sd = data.Mode.GetSectorData(ld.Back.Sector);
                            sd.AddUpdateSector(data.Sector, true);
                            td.AddUpdateSector(ld.Back.Sector, true);
                            if (!sd.Updated)
                            {
                                sd.Update();
                            }
                            sd.Ceiling.plane = new Plane(v2, v1, v3, false);
                        }
                    }
                }
            }
        }
Exemplo n.º 8
0
        // This builds the geometry. Returns false when no geometry created.
        public override bool Setup()
        {
            Vector2D vl, vr;

            int  lightvalue    = Sidedef.Fields.GetValue("light", 0);
            bool lightabsolute = Sidedef.Fields.GetValue("lightabsolute", false);

            Vector2D tscale = new Vector2D(Sidedef.Fields.GetValue("scalex_mid", 1.0f),
                                           Sidedef.Fields.GetValue("scaley_mid", 1.0f));
            Vector2D toffset = new Vector2D(Sidedef.Fields.GetValue("offsetx_mid", 0.0f),
                                            Sidedef.Fields.GetValue("offsety_mid", 0.0f));

            // Texture given?
            if ((Sidedef.MiddleTexture.Length > 0) && (Sidedef.MiddleTexture[0] != '-'))
            {
                // Left and right vertices for this sidedef
                if (Sidedef.IsFront)
                {
                    vl = new Vector2D(Sidedef.Line.Start.Position.x, Sidedef.Line.Start.Position.y);
                    vr = new Vector2D(Sidedef.Line.End.Position.x, Sidedef.Line.End.Position.y);
                }
                else
                {
                    vl = new Vector2D(Sidedef.Line.End.Position.x, Sidedef.Line.End.Position.y);
                    vr = new Vector2D(Sidedef.Line.Start.Position.x, Sidedef.Line.Start.Position.y);
                }

                // Load sector data
                SectorData sd  = mode.GetSectorData(Sidedef.Sector);
                SectorData osd = mode.GetSectorData(Sidedef.Other.Sector);
                if (!osd.Updated)
                {
                    osd.Update();
                }

                // Texture given?
                if ((Sidedef.MiddleTexture.Length > 0) && (Sidedef.MiddleTexture[0] != '-'))
                {
                    // Load texture
                    base.Texture = General.Map.Data.GetTextureImage(Sidedef.LongMiddleTexture);
                    if (base.Texture == null)
                    {
                        base.Texture         = General.Map.Data.MissingTexture3D;
                        setuponloadedtexture = Sidedef.LongMiddleTexture;
                    }
                    else
                    {
                        if (!base.Texture.IsImageLoaded)
                        {
                            setuponloadedtexture = Sidedef.LongMiddleTexture;
                        }
                    }
                }
                else
                {
                    // Use missing texture
                    base.Texture         = General.Map.Data.MissingTexture3D;
                    setuponloadedtexture = 0;
                }

                // Get texture scaled size
                Vector2D tsz = new Vector2D(base.Texture.ScaledWidth, base.Texture.ScaledHeight);
                tsz = tsz / tscale;

                // Get texture offsets
                Vector2D tof = new Vector2D(Sidedef.OffsetX, Sidedef.OffsetY);
                tof = tof + toffset;
                tof = tof / tscale;
                if (General.Map.Config.ScaledTextureOffsets && !base.Texture.WorldPanning)
                {
                    tof = tof * base.Texture.Scale;
                }

                // Determine texture coordinates plane as they would be in normal circumstances.
                // We can then use this plane to find any texture coordinate we need.
                // The logic here is the same as in the original VisualMiddleSingle (except that
                // the values are stored in a TexturePlane)
                // NOTE: I use a small bias for the floor height, because if the difference in
                // height is 0 then the TexturePlane doesn't work!
                TexturePlane tp        = new TexturePlane();
                float        floorbias = (Sidedef.Sector.CeilHeight == Sidedef.Sector.FloorHeight) ? 1.0f : 0.0f;
                float        geotop    = (float)Math.Min(Sidedef.Sector.CeilHeight, Sidedef.Other.Sector.CeilHeight);
                float        geobottom = (float)Math.Max(Sidedef.Sector.FloorHeight, Sidedef.Other.Sector.FloorHeight);
                if (Sidedef.Line.IsFlagSet(General.Map.Config.LowerUnpeggedFlag))
                {
                    // When lower unpegged is set, the middle texture is bound to the bottom
                    tp.tlt.y = tsz.y - (float)(geotop - geobottom);
                }
                tp.trb.x = tp.tlt.x + Sidedef.Line.Length;
                tp.trb.y = tp.tlt.y + ((float)Sidedef.Sector.CeilHeight - ((float)Sidedef.Sector.FloorHeight + floorbias));

                // Apply texture offset
                tp.tlt += tof;
                tp.trb += tof;

                // Transform pixel coordinates to texture coordinates
                tp.tlt /= tsz;
                tp.trb /= tsz;

                // Left top and right bottom of the geometry that
                tp.vlt = new Vector3D(vl.x, vl.y, (float)Sidedef.Sector.CeilHeight);
                tp.vrb = new Vector3D(vr.x, vr.y, (float)Sidedef.Sector.FloorHeight + floorbias);

                // Make the right-top coordinates
                tp.trt = new Vector2D(tp.trb.x, tp.tlt.y);
                tp.vrt = new Vector3D(tp.vrb.x, tp.vrb.y, tp.vlt.z);

                // Keep top and bottom planes for intersection testing
                top    = sd.Ceiling.plane;
                bottom = sd.Floor.plane;

                // Create initial polygon, which is just a quad between floor and ceiling
                WallPolygon poly = new WallPolygon();
                poly.Add(new Vector3D(vl.x, vl.y, sd.Floor.plane.GetZ(vl)));
                poly.Add(new Vector3D(vl.x, vl.y, sd.Ceiling.plane.GetZ(vl)));
                poly.Add(new Vector3D(vr.x, vr.y, sd.Ceiling.plane.GetZ(vr)));
                poly.Add(new Vector3D(vr.x, vr.y, sd.Floor.plane.GetZ(vr)));

                // Determine initial color
                int        lightlevel     = lightabsolute ? lightvalue : sd.Ceiling.brightnessbelow + lightvalue;
                PixelColor wallbrightness = PixelColor.FromInt(mode.CalculateBrightness(lightlevel));
                PixelColor wallcolor      = PixelColor.Modulate(sd.Ceiling.colorbelow, wallbrightness);
                poly.color = wallcolor.WithAlpha(255).ToInt();

                // Cut off the part below the other floor and above the other ceiling
                CropPoly(ref poly, osd.Ceiling.plane, true);
                CropPoly(ref poly, osd.Floor.plane, true);

                // Determine if we should repeat the middle texture
                if (Sidedef.Fields.ContainsKey("wrapmidtex"))
                {
                    repeatmidtex = Sidedef.Fields.GetValue("wrapmidtex", false);
                }
                else
                {
                    repeatmidtex = Sidedef.Line.IsFlagSet("wrapmidtex");
                }

                if (!repeatmidtex)
                {
                    // First determine the visible portion of the texture
                    float textop, texbottom;

                    // Determine top portion height
                    if (Sidedef.Line.IsFlagSet(General.Map.Config.LowerUnpeggedFlag))
                    {
                        textop = geobottom + tof.y + tsz.y;
                    }
                    else
                    {
                        textop = geotop + tof.y;
                    }

                    // Calculate bottom portion height
                    texbottom = textop - tsz.y;

                    // Create crop planes (we also need these for intersection testing)
                    topclipplane    = new Plane(new Vector3D(0, 0, -1), textop);
                    bottomclipplane = new Plane(new Vector3D(0, 0, 1), -texbottom);

                    // Crop polygon by these heights
                    CropPoly(ref poly, topclipplane, true);
                    CropPoly(ref poly, bottomclipplane, true);
                }

                if (poly.Count > 2)
                {
                    // Keep top and bottom planes for intersection testing
                    top    = osd.Ceiling.plane;
                    bottom = osd.Floor.plane;

                    // Process the polygon and create vertices
                    List <WorldVertex> verts = CreatePolygonVertices(poly, tp, sd, lightvalue, lightabsolute);
                    if (verts.Count > 0)
                    {
                        // Apply alpha to vertices
                        byte alpha = SetLinedefRenderstyle(true);
                        if (alpha < 255)
                        {
                            for (int i = 0; i < verts.Count; i++)
                            {
                                WorldVertex v = verts[i];
                                PixelColor  c = PixelColor.FromInt(v.c);
                                v.c      = c.WithAlpha(alpha).ToInt();
                                verts[i] = v;
                            }
                        }

                        base.SetVertices(verts);
                        return(true);
                    }
                }
            }

            return(false);
        }
Exemplo n.º 9
0
        // This builds the thing geometry. Returns false when nothing was created.
        public virtual bool Setup()
        {
            PixelColor sectorcolor = new PixelColor(255, 255, 255, 255);

            // Must have a width and height!
            if ((info.Radius < 0.1f) || (info.Height < 0.1f))
            {
                return(false);
            }

            // Find the sector in which the thing resides
            Thing.DetermineSector(mode.BlockMap);

            if (sprite != null)
            {
                if (Thing.Sector != null)
                {
                    SectorData  sd    = mode.GetSectorData(Thing.Sector);
                    SectorLevel level = sd.GetLevelAbove(new Vector3D(Thing.Position.x, Thing.Position.y, Thing.Position.z + Thing.Sector.FloorHeight));
                    if (level != null)
                    {
                        // Use sector brightness for color shading
                        PixelColor areabrightness = PixelColor.FromInt(mode.CalculateBrightness(level.brightnessbelow));
                        PixelColor areacolor      = PixelColor.Modulate(level.colorbelow, areabrightness);
                        sectorcolor = areacolor.WithAlpha(255);
                    }
                }

                // Check if the texture is loaded
                sprite.LoadImage();
                isloaded = sprite.IsImageLoaded;
                if (isloaded)
                {
                    float offsetx = 0.0f;
                    float offsety = 0.0f;

                    base.Texture = sprite;

                    // Determine sprite size and offset
                    float radius = sprite.ScaledWidth * 0.5f;
                    float height = sprite.ScaledHeight;
                    if (sprite is SpriteImage)
                    {
                        offsetx = (sprite as SpriteImage).OffsetX - radius;
                        offsety = (sprite as SpriteImage).OffsetY - height;
                    }

                    // Scale by thing type/actor scale
                    // We do this after the offset x/y determination above, because that is entirely in sprite pixels space
                    radius  *= info.SpriteScale.Width;
                    height  *= info.SpriteScale.Height;
                    offsetx *= info.SpriteScale.Width;
                    offsety *= info.SpriteScale.Height;

                    // Make vertices
                    WorldVertex[] verts = new WorldVertex[6];
                    verts[0] = new WorldVertex(-radius + offsetx, 0.0f, 0.0f + offsety, sectorcolor.ToInt(), 0.0f, 1.0f);
                    verts[1] = new WorldVertex(-radius + offsetx, 0.0f, height + offsety, sectorcolor.ToInt(), 0.0f, 0.0f);
                    verts[2] = new WorldVertex(+radius + offsetx, 0.0f, height + offsety, sectorcolor.ToInt(), 1.0f, 0.0f);
                    verts[3] = verts[0];
                    verts[4] = verts[2];
                    verts[5] = new WorldVertex(+radius + offsetx, 0.0f, 0.0f + offsety, sectorcolor.ToInt(), 1.0f, 1.0f);
                    SetVertices(verts);
                }
                else
                {
                    base.Texture = General.Map.Data.Hourglass3D;

                    // Determine sprite size
                    float radius = Math.Min(info.Radius, info.Height / 2f);
                    float height = Math.Min(info.Radius * 2f, info.Height);

                    // Make vertices
                    WorldVertex[] verts = new WorldVertex[6];
                    verts[0] = new WorldVertex(-radius, 0.0f, 0.0f, sectorcolor.ToInt(), 0.0f, 1.0f);
                    verts[1] = new WorldVertex(-radius, 0.0f, height, sectorcolor.ToInt(), 0.0f, 0.0f);
                    verts[2] = new WorldVertex(+radius, 0.0f, height, sectorcolor.ToInt(), 1.0f, 0.0f);
                    verts[3] = verts[0];
                    verts[4] = verts[2];
                    verts[5] = new WorldVertex(+radius, 0.0f, 0.0f, sectorcolor.ToInt(), 1.0f, 1.0f);
                    SetVertices(verts);
                }
            }

            // Determine position
            Vector3D pos = Thing.Position;

            if (Thing.Type == 9501)
            {
                // This is a special thing that needs special positioning
                SectorData sd = mode.GetSectorData(Thing.Sector);
                pos.z = sd.Ceiling.sector.CeilHeight + Thing.Position.z;
            }
            else if (Thing.Type == 9500)
            {
                // This is a special thing that needs special positioning
                SectorData sd = mode.GetSectorData(Thing.Sector);
                pos.z = sd.Floor.sector.FloorHeight + Thing.Position.z;
            }
            else if (info.AbsoluteZ)
            {
                // Absolute Z position
                pos.z = Thing.Position.z;
            }
            else if (info.Hangs)
            {
                // Hang from ceiling
                if (Thing.Sector != null)
                {
                    SectorData sd = mode.GetSectorData(Thing.Sector);
                    if (Thing.Position.z > 0)
                    {
                        pos.z = sd.Ceiling.plane.GetZ(Thing.Position) - info.Height;
                    }
                    else
                    {
                        pos.z = Thing.Sector.CeilHeight - info.Height;
                    }
                }

                pos.z -= Thing.Position.z;

                // Check if below floor
                if ((Thing.Sector != null) && (pos.z < Thing.Sector.FloorHeight))
                {
                    // Put thing on the floor
                    SectorData sd = mode.GetSectorData(Thing.Sector);
                    pos.z = sd.Floor.plane.GetZ(Thing.Position);
                }
            }
            else
            {
                // Stand on floor
                if (Thing.Sector != null)
                {
                    SectorData sd = mode.GetSectorData(Thing.Sector);
                    if (Thing.Position.z == 0)
                    {
                        pos.z = sd.Floor.plane.GetZ(Thing.Position);
                    }
                    else
                    {
                        pos.z = Thing.Sector.FloorHeight;
                    }
                }

                pos.z += Thing.Position.z;

                // Check if above ceiling
                if ((Thing.Sector != null) && ((pos.z + info.Height) > Thing.Sector.CeilHeight))
                {
                    // Put thing against ceiling
                    SectorData sd = mode.GetSectorData(Thing.Sector);
                    pos.z = sd.Ceiling.plane.GetZ(Thing.Position) - info.Height;
                }
            }

            // Apply settings
            SetPosition(pos);
            SetCageSize(info.Radius, info.Height);
            SetCageColor(Thing.Color);

            // Keep info for object picking
            cageradius2 = info.Radius * Angle2D.SQRT2;
            cageradius2 = cageradius2 * cageradius2;
            pos2d       = pos;
            boxp1       = new Vector3D(pos.x - info.Radius, pos.y - info.Radius, pos.z);
            boxp2       = new Vector3D(pos.x + info.Radius, pos.y + info.Radius, pos.z + info.Height);

            // Done
            changed = false;
            return(true);
        }
Exemplo n.º 10
0
 // Constructor
 protected SectorEffect(SectorData data)
 {
     this.data = data;
 }
Exemplo n.º 11
0
        // This (re)builds the visual sector, calculating all geometry from scratch
        public void Rebuild()
        {
            // Forget old geometry
            base.ClearGeometry();

            // Get sector data
            SectorData data = GetSectorData();

            if (!data.Updated)
            {
                data.Update();
            }

            // Create floor
            floor = floor ?? new VisualFloor(mode, this);
            if (floor.Setup(data.Floor, null))
            {
                base.AddGeometry(floor);
            }

            // Create ceiling
            ceiling = ceiling ?? new VisualCeiling(mode, this);
            if (ceiling.Setup(data.Ceiling, null))
            {
                base.AddGeometry(ceiling);
            }

            // Create 3D floors
            for (int i = 0; i < data.ExtraFloors.Count; i++)
            {
                Effect3DFloor ef = data.ExtraFloors[i];

                // Create a floor
                VisualFloor vf = (i < extrafloors.Count) ? extrafloors[i] : new VisualFloor(mode, this);
                if (vf.Setup(ef.Ceiling, ef))
                {
                    base.AddGeometry(vf);
                }
                if (i >= extrafloors.Count)
                {
                    extrafloors.Add(vf);
                }

                // Create a ceiling
                VisualCeiling vc = (i < extraceilings.Count) ? extraceilings[i] : new VisualCeiling(mode, this);
                if (vc.Setup(ef.Floor, ef))
                {
                    base.AddGeometry(vc);
                }
                if (i >= extraceilings.Count)
                {
                    extraceilings.Add(vc);
                }
            }

            // Go for all sidedefs
            Dictionary <Sidedef, VisualSidedefParts> oldsides = sides ?? new Dictionary <Sidedef, VisualSidedefParts>(1);

            sides = new Dictionary <Sidedef, VisualSidedefParts>(base.Sector.Sidedefs.Count);
            foreach (Sidedef sd in base.Sector.Sidedefs)
            {
                // VisualSidedef already exists?
                VisualSidedefParts parts = oldsides.ContainsKey(sd) ? oldsides[sd] : new VisualSidedefParts();

                // Doublesided or singlesided?
                if (sd.Other != null)
                {
                    // Create upper part
                    VisualUpper vu = parts.upper ?? new VisualUpper(mode, this, sd);
                    if (vu.Setup())
                    {
                        base.AddGeometry(vu);
                    }

                    // Create lower part
                    VisualLower vl = parts.lower ?? new VisualLower(mode, this, sd);
                    if (vl.Setup())
                    {
                        base.AddGeometry(vl);
                    }

                    // Create middle part
                    VisualMiddleDouble vm = parts.middledouble ?? new VisualMiddleDouble(mode, this, sd);
                    if (vm.Setup())
                    {
                        base.AddGeometry(vm);
                    }

                    // Create 3D wall parts
                    SectorData osd = mode.GetSectorData(sd.Other.Sector);
                    if (!osd.Updated)
                    {
                        osd.Update();
                    }
                    List <VisualMiddle3D> middles = parts.middle3d ?? new List <VisualMiddle3D>(osd.ExtraFloors.Count);
                    for (int i = 0; i < osd.ExtraFloors.Count; i++)
                    {
                        Effect3DFloor ef = osd.ExtraFloors[i];

                        VisualMiddle3D vm3 = (i < middles.Count) ? middles[i] : new VisualMiddle3D(mode, this, sd);
                        if (vm3.Setup(ef))
                        {
                            base.AddGeometry(vm3);
                        }
                        if (i >= middles.Count)
                        {
                            middles.Add(vm3);
                        }
                    }

                    // Store
                    sides.Add(sd, new VisualSidedefParts(vu, vl, vm, middles));
                }
                else
                {
                    // Create middle part
                    VisualMiddleSingle vm = parts.middlesingle ?? new VisualMiddleSingle(mode, this, sd);
                    if (vm.Setup())
                    {
                        base.AddGeometry(vm);
                    }

                    // Store
                    sides.Add(sd, new VisualSidedefParts(vm));
                }
            }

            // Done
            changed = false;
        }
Exemplo n.º 12
0
        // This makes sure we are updated with the source linedef information
        public override void Update()
        {
            SectorData sd = data.Mode.GetSectorData(linedef.Front.Sector);

            if (!sd.Updated)
            {
                sd.Update();
            }
            sd.AddUpdateSector(data.Sector, true);

            // Check if this effect still exists
            int sectortag = linedef.Args[0] + (linedef.Args[4] << 8);

            if (linedef.IsDisposed || (linedef.Action != 160) || (sectortag != data.Sector.Tag))
            {
                // When the effect is no longer exists, we must remove it and update sectors
            }

            if (floor == null)
            {
                floor = new SectorLevel(sd.Floor);
                data.AddSectorLevel(floor);
            }

            if (ceiling == null)
            {
                ceiling = new SectorLevel(sd.Ceiling);
                data.AddSectorLevel(ceiling);
            }

            // For non-vavoom types, we must switch the level types
            int argtype = (linedef.Args[1] & 0x03);

            if (argtype != 0)
            {
                vavoomtype = false;
                alpha      = linedef.Args[3];
                sd.Ceiling.CopyProperties(floor);
                sd.Floor.CopyProperties(ceiling);
                floor.type    = SectorLevelType.Floor;
                floor.plane   = sd.Ceiling.plane.GetInverted();
                ceiling.type  = SectorLevelType.Ceiling;
                ceiling.plane = sd.Floor.plane.GetInverted();

                // A 3D floor's color is always that of the sector it is placed in
                floor.color = 0;
            }
            else
            {
                vavoomtype = true;

                /*
                 * sd.Ceiling.CopyProperties(floor);
                 * sd.Floor.CopyProperties(ceiling);
                 */
                floor.type    = SectorLevelType.Ceiling;
                floor.plane   = sd.Ceiling.plane;
                ceiling.type  = SectorLevelType.Floor;
                ceiling.plane = sd.Floor.plane;
                alpha         = 255;

                // A 3D floor's color is always that of the sector it is placed in
                ceiling.color = 0;
            }

            // Apply alpha
            floor.alpha   = alpha;
            ceiling.alpha = alpha;

            // Do not adjust light? (works only for non-vavoom types)
            if (((linedef.Args[2] & 1) != 0) && !vavoomtype)
            {
                floor.brightnessbelow   = -1;
                floor.colorbelow        = PixelColor.FromInt(0);
                ceiling.color           = 0;
                ceiling.brightnessbelow = -1;
                ceiling.colorbelow      = PixelColor.FromInt(0);
            }
        }
Exemplo n.º 13
0
        // This builds the geometry. Returns false when no geometry created.
        public override bool Setup()
        {
            Vector2D vl, vr;

            int  lightvalue    = Sidedef.Fields.GetValue("light", 0);
            bool lightabsolute = Sidedef.Fields.GetValue("lightabsolute", false);

            Vector2D tscale = new Vector2D(Sidedef.Fields.GetValue("scalex_mid", 1.0f),
                                           Sidedef.Fields.GetValue("scaley_mid", 1.0f));
            Vector2D toffset = new Vector2D(Sidedef.Fields.GetValue("offsetx_mid", 0.0f),
                                            Sidedef.Fields.GetValue("offsety_mid", 0.0f));

            // Left and right vertices for this sidedef
            if (Sidedef.IsFront)
            {
                vl = new Vector2D(Sidedef.Line.Start.Position.x, Sidedef.Line.Start.Position.y);
                vr = new Vector2D(Sidedef.Line.End.Position.x, Sidedef.Line.End.Position.y);
            }
            else
            {
                vl = new Vector2D(Sidedef.Line.End.Position.x, Sidedef.Line.End.Position.y);
                vr = new Vector2D(Sidedef.Line.Start.Position.x, Sidedef.Line.Start.Position.y);
            }

            // Load sector data
            SectorData sd = mode.GetSectorData(Sidedef.Sector);

            // Texture given?
            if ((Sidedef.MiddleTexture.Length > 0) && (Sidedef.MiddleTexture[0] != '-'))
            {
                // Load texture
                base.Texture = General.Map.Data.GetTextureImage(Sidedef.LongMiddleTexture);
                if (base.Texture == null)
                {
                    base.Texture         = General.Map.Data.MissingTexture3D;
                    setuponloadedtexture = Sidedef.LongMiddleTexture;
                }
                else
                {
                    if (!base.Texture.IsImageLoaded)
                    {
                        setuponloadedtexture = Sidedef.LongMiddleTexture;
                    }
                }
            }
            else
            {
                // Use missing texture
                base.Texture         = General.Map.Data.MissingTexture3D;
                setuponloadedtexture = 0;
            }

            // Get texture scaled size
            Vector2D tsz = new Vector2D(base.Texture.ScaledWidth, base.Texture.ScaledHeight);

            tsz = tsz / tscale;

            // Get texture offsets
            Vector2D tof = new Vector2D(Sidedef.OffsetX, Sidedef.OffsetY);

            tof = tof + toffset;
            tof = tof / tscale;
            if (General.Map.Config.ScaledTextureOffsets && !base.Texture.WorldPanning)
            {
                tof = tof * base.Texture.Scale;
            }

            // Determine texture coordinates plane as they would be in normal circumstances.
            // We can then use this plane to find any texture coordinate we need.
            // The logic here is the same as in the original VisualMiddleSingle (except that
            // the values are stored in a TexturePlane)
            // NOTE: I use a small bias for the floor height, because if the difference in
            // height is 0 then the TexturePlane doesn't work!
            TexturePlane tp        = new TexturePlane();
            float        floorbias = (Sidedef.Sector.CeilHeight == Sidedef.Sector.FloorHeight) ? 1.0f : 0.0f;

            if (Sidedef.Line.IsFlagSet(General.Map.Config.LowerUnpeggedFlag))
            {
                // When lower unpegged is set, the middle texture is bound to the bottom
                tp.tlt.y = tsz.y - (float)(Sidedef.Sector.CeilHeight - Sidedef.Sector.FloorHeight);
            }
            tp.trb.x = tp.tlt.x + Sidedef.Line.Length;
            tp.trb.y = tp.tlt.y + ((float)Sidedef.Sector.CeilHeight - ((float)Sidedef.Sector.FloorHeight + floorbias));

            // Apply texture offset
            tp.tlt += tof;
            tp.trb += tof;

            // Transform pixel coordinates to texture coordinates
            tp.tlt /= tsz;
            tp.trb /= tsz;

            // Left top and right bottom of the geometry that
            tp.vlt = new Vector3D(vl.x, vl.y, (float)Sidedef.Sector.CeilHeight);
            tp.vrb = new Vector3D(vr.x, vr.y, (float)Sidedef.Sector.FloorHeight + floorbias);

            // Make the right-top coordinates
            tp.trt = new Vector2D(tp.trb.x, tp.tlt.y);
            tp.vrt = new Vector3D(tp.vrb.x, tp.vrb.y, tp.vlt.z);

            // Get ceiling and floor heights
            float fl = sd.Floor.plane.GetZ(vl);
            float fr = sd.Floor.plane.GetZ(vr);
            float cl = sd.Ceiling.plane.GetZ(vl);
            float cr = sd.Ceiling.plane.GetZ(vr);

            // Anything to see?
            if (((cl - fl) > 0.01f) || ((cr - fr) > 0.01f))
            {
                // Keep top and bottom planes for intersection testing
                top    = sd.Ceiling.plane;
                bottom = sd.Floor.plane;

                // Create initial polygon, which is just a quad between floor and ceiling
                WallPolygon poly = new WallPolygon();
                poly.Add(new Vector3D(vl.x, vl.y, fl));
                poly.Add(new Vector3D(vl.x, vl.y, cl));
                poly.Add(new Vector3D(vr.x, vr.y, cr));
                poly.Add(new Vector3D(vr.x, vr.y, fr));

                // Determine initial color
                int        lightlevel     = lightabsolute ? lightvalue : sd.Ceiling.brightnessbelow + lightvalue;
                PixelColor wallbrightness = PixelColor.FromInt(mode.CalculateBrightness(lightlevel));
                PixelColor wallcolor      = PixelColor.Modulate(sd.Ceiling.colorbelow, wallbrightness);
                poly.color = wallcolor.WithAlpha(255).ToInt();

                // Process the polygon and create vertices
                List <WorldVertex> verts = CreatePolygonVertices(poly, tp, sd, lightvalue, lightabsolute);
                if (verts.Count > 0)
                {
                    base.SetVertices(verts);
                    return(true);
                }
            }

            return(false);
        }
Exemplo n.º 14
0
        // This makes sure we are updated with the source linedef information
        public override void Update()
        {
            Linedef l = linedef;

            // Find the vertex furthest from the line
            Vertex foundv    = null;
            float  founddist = -1.0f;

            foreach (Sidedef sd in data.Sector.Sidedefs)
            {
                Vertex v = sd.IsFront ? sd.Line.Start : sd.Line.End;
                float  d = l.DistanceToSq(v.Position, false);
                if (d > founddist)
                {
                    foundv    = v;
                    founddist = d;
                }
            }

            // Align floor with back of line
            if ((l.Args[0] == 1) && (l.Front.Sector == data.Sector) && (l.Back != null))
            {
                Vector3D v1 = new Vector3D(l.Start.Position.x, l.Start.Position.y, l.Back.Sector.FloorHeight);
                Vector3D v2 = new Vector3D(l.End.Position.x, l.End.Position.y, l.Back.Sector.FloorHeight);
                Vector3D v3 = new Vector3D(foundv.Position.x, foundv.Position.y, data.Sector.FloorHeight);
                if (l.SideOfLine(v3) < 0.0f)
                {
                    data.Floor.plane = new Plane(v1, v2, v3, true);
                }
                else
                {
                    data.Floor.plane = new Plane(v2, v1, v3, true);
                }
                SectorData sd = data.Mode.GetSectorData(l.Back.Sector);
                sd.AddUpdateSector(data.Sector, true);
            }
            // Align floor with front of line
            else if ((l.Args[0] == 2) && (l.Back.Sector == data.Sector) && (l.Front != null))
            {
                Vector3D v1 = new Vector3D(l.Start.Position.x, l.Start.Position.y, l.Front.Sector.FloorHeight);
                Vector3D v2 = new Vector3D(l.End.Position.x, l.End.Position.y, l.Front.Sector.FloorHeight);
                Vector3D v3 = new Vector3D(foundv.Position.x, foundv.Position.y, data.Sector.FloorHeight);
                if (l.SideOfLine(v3) < 0.0f)
                {
                    data.Floor.plane = new Plane(v1, v2, v3, true);
                }
                else
                {
                    data.Floor.plane = new Plane(v2, v1, v3, true);
                }
                SectorData sd = data.Mode.GetSectorData(l.Front.Sector);
                sd.AddUpdateSector(data.Sector, true);
            }

            // Align ceiling with back of line
            if ((l.Args[1] == 1) && (l.Front.Sector == data.Sector) && (l.Back != null))
            {
                Vector3D v1 = new Vector3D(l.Start.Position.x, l.Start.Position.y, l.Back.Sector.CeilHeight);
                Vector3D v2 = new Vector3D(l.End.Position.x, l.End.Position.y, l.Back.Sector.CeilHeight);
                Vector3D v3 = new Vector3D(foundv.Position.x, foundv.Position.y, data.Sector.CeilHeight);
                if (l.SideOfLine(v3) > 0.0f)
                {
                    data.Ceiling.plane = new Plane(v1, v2, v3, false);
                }
                else
                {
                    data.Ceiling.plane = new Plane(v2, v1, v3, false);
                }
                SectorData sd = data.Mode.GetSectorData(l.Back.Sector);
                sd.AddUpdateSector(data.Sector, true);
            }
            // Align ceiling with front of line
            else if ((l.Args[1] == 2) && (l.Back.Sector == data.Sector) && (l.Front != null))
            {
                Vector3D v1 = new Vector3D(l.Start.Position.x, l.Start.Position.y, l.Front.Sector.CeilHeight);
                Vector3D v2 = new Vector3D(l.End.Position.x, l.End.Position.y, l.Front.Sector.CeilHeight);
                Vector3D v3 = new Vector3D(foundv.Position.x, foundv.Position.y, data.Sector.CeilHeight);
                if (l.SideOfLine(v3) > 0.0f)
                {
                    data.Ceiling.plane = new Plane(v1, v2, v3, false);
                }
                else
                {
                    data.Ceiling.plane = new Plane(v2, v1, v3, false);
                }
                SectorData sd = data.Mode.GetSectorData(l.Front.Sector);
                sd.AddUpdateSector(data.Sector, true);
            }
        }