示例#1
0
 // Copy properties
 public void CopyProperties(SectorLevel target)
 {
     target.sector          = this.sector;
     target.type            = this.type;
     target.plane           = this.plane;
     target.alpha           = this.alpha;
     target.color           = this.color;
     target.brightnessbelow = this.brightnessbelow;
     target.colorbelow      = this.colorbelow;
 }
示例#2
0
        // When no geometry has been changed and no effects have been added or removed,
        // you can call this again to update existing effects. The effects will update
        // the existing SectorLevels to match with any changes.
        public void Update()
        {
            if (isupdating || updated)
            {
                return;
            }
            isupdating = true;

            // Set floor/ceiling to their original setup
            BasicSetup();

            // Update all effects
            foreach (SectorEffect e in alleffects)
            {
                e.Update();
            }

            // Sort the levels (but not the first and the last)
            SectorLevelComparer comparer = new SectorLevelComparer(sector);

            lightlevels.Sort(1, lightlevels.Count - 2, comparer);

            // Now that we know the levels in this sector (and in the right order) we
            // can determine the lighting in between and on the levels.
            // Start from the absolute ceiling and go down to 'cast' the lighting
            for (int i = lightlevels.Count - 2; i >= 0; i--)
            {
                SectorLevel l  = lightlevels[i];
                SectorLevel pl = lightlevels[i + 1];

                // Set color when no color is specified, or when a 3D floor is placed above the absolute floor
                if ((l.color == 0) || ((l == floor) && (lightlevels.Count > 2)))
                {
                    PixelColor floorbrightness = PixelColor.FromInt(mode.CalculateBrightness(pl.brightnessbelow));
                    PixelColor floorcolor      = PixelColor.Modulate(pl.colorbelow, floorbrightness);
                    l.color = floorcolor.WithAlpha(255).ToInt();
                }

                if (l.colorbelow.a == 0)
                {
                    l.colorbelow = pl.colorbelow;
                }

                if (l.brightnessbelow == -1)
                {
                    l.brightnessbelow = pl.brightnessbelow;
                }
            }

            floorchanged   = false;
            ceilingchanged = false;
            updated        = true;
            isupdating     = false;
        }
示例#3
0
        // This returns the level below the given point
        public SectorLevel GetLevelBelow(Vector3D pos)
        {
            SectorLevel found = null;
            float       dist  = float.MaxValue;

            foreach (SectorLevel l in lightlevels)
            {
                float d = pos.z - l.plane.GetZ(pos);
                if ((d > 0.0f) && (d < dist))
                {
                    dist  = d;
                    found = l;
                }
            }

            return(found);
        }
示例#4
0
        // This returns the level above the given point
        public SectorLevel GetCeilingAbove(Vector3D pos)
        {
            SectorLevel found = null;
            float       dist  = float.MaxValue;

            foreach (SectorLevel l in lightlevels)
            {
                if (l.type == SectorLevelType.Ceiling)
                {
                    float d = l.plane.GetZ(pos) - pos.z;
                    if ((d > 0.0f) && (d < dist))
                    {
                        dist  = d;
                        found = l;
                    }
                }
            }

            return(found);
        }
        // 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;
        }
示例#6
0
        // Constructor
        public SectorData(BaseVisualMode mode, Sector s)
        {
            // Initialize
            this.mode           = mode;
            this.sector         = s;
            this.updated        = false;
            this.floorchanged   = false;
            this.ceilingchanged = false;
            this.lightlevels    = new List <SectorLevel>(2);
            this.extrafloors    = new List <Effect3DFloor>(1);
            this.alleffects     = new List <SectorEffect>(1);
            this.updatesectors  = new Dictionary <Sector, bool>(2);
            this.floor          = new SectorLevel(sector, SectorLevelType.Floor);
            this.ceiling        = new SectorLevel(sector, SectorLevelType.Ceiling);

            BasicSetup();

            // Add ceiling and floor
            lightlevels.Add(floor);
            lightlevels.Add(ceiling);
        }
示例#7
0
        // This builds the geometry. Returns false when no geometry created.
        public override bool Setup(SectorLevel level, Effect3DFloor extrafloor)
        {
            WorldVertex[] verts;
            Sector        s = level.sector;
            Vector2D      texscale;

            base.Setup(level, extrafloor);

            // Fetch ZDoom fields
            float    rotate = Angle2D.DegToRad(s.Fields.GetValue("rotationceiling", 0.0f));
            Vector2D offset = new Vector2D(s.Fields.GetValue("xpanningceiling", 0.0f),
                                           s.Fields.GetValue("ypanningceiling", 0.0f));
            Vector2D scale = new Vector2D(s.Fields.GetValue("xscaleceiling", 1.0f),
                                          s.Fields.GetValue("yscaleceiling", 1.0f));

            // Load floor texture
            base.Texture = General.Map.Data.GetFlatImage(s.LongCeilTexture);
            if (base.Texture == null)
            {
                base.Texture         = General.Map.Data.MissingTexture3D;
                setuponloadedtexture = s.LongCeilTexture;
            }
            else
            {
                if (!base.Texture.IsImageLoaded)
                {
                    setuponloadedtexture = s.LongCeilTexture;
                }
            }

            // Determine texture scale
            if (base.Texture.IsImageLoaded)
            {
                texscale = new Vector2D(1.0f / base.Texture.ScaledWidth, 1.0f / base.Texture.ScaledHeight);
            }
            else
            {
                texscale = new Vector2D(1.0f / 64.0f, 1.0f / 64.0f);
            }

            // Make vertices
            ReadOnlyCollection <Vector2D> triverts = base.Sector.Sector.Triangles.Vertices;

            verts = new WorldVertex[triverts.Count];
            for (int i = 0; i < triverts.Count; i++)
            {
                // Color shading
                PixelColor c = PixelColor.FromInt(level.color);
                verts[i].c = c.WithAlpha((byte)General.Clamp(level.alpha, 0, 255)).ToInt();

                // Vertex coordinates
                verts[i].x = triverts[i].x;
                verts[i].y = triverts[i].y;
                verts[i].z = level.plane.GetZ(triverts[i]);                 //(float)s.CeilHeight;

                // Texture coordinates
                Vector2D pos = triverts[i];
                pos        = pos.GetRotated(rotate);
                pos.y      = -pos.y;
                pos        = (pos + offset) * scale * texscale;
                verts[i].u = pos.x;
                verts[i].v = pos.y;
            }

            // The sector triangulation created clockwise triangles that
            // are right up for the floor. For the ceiling we must flip
            // the triangles upside down.
            if ((extrafloor == null) || extrafloor.VavoomType)
            {
                SwapTriangleVertices(verts);
            }

            // Determine render pass
            if (extrafloor != null)
            {
                if (level.alpha < 255)
                {
                    this.RenderPass = RenderPass.Alpha;
                }
                else
                {
                    this.RenderPass = RenderPass.Mask;
                }
            }
            else
            {
                this.RenderPass = RenderPass.Solid;
            }

            // Apply vertices
            base.SetVertices(verts);
            return(verts.Length > 0);
        }
        // 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);
        }
示例#9
0
 // This adds a sector level
 public void AddSectorLevel(SectorLevel level)
 {
     // Note: Inserting before the end so that the ceiling stays
     // at the end and the floor at the beginning
     lightlevels.Insert(lightlevels.Count - 1, level);
 }
示例#10
0
 // Copy constructor
 public SectorLevel(SectorLevel source)
 {
     source.CopyProperties(this);
 }
示例#11
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);
        }
示例#12
0
 public virtual bool Setup(SectorLevel level, Effect3DFloor extrafloor)
 {
     this.level      = level;
     this.extrafloor = extrafloor;
     return(false);
 }
示例#13
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);
            }
        }