Beispiel #1
0
        //mxd
        private int GetLevelColor(SectorLevel src)
        {
            PixelColor brightness = PixelColor.FromInt(mode.CalculateBrightness(src.brightnessbelow));
            PixelColor color      = PixelColor.Modulate(src.colorbelow, brightness);

            return(color.WithAlpha(255).ToInt());
        }
Beispiel #2
0
 //mxd. Compare light properties
 public bool LightPropertiesMatch(SectorLevel other)
 {
     return(this.type == other.type && this.lighttype == other.lighttype && this.alpha == other.alpha && this.splitsides == other.splitsides &&
            this.color == other.color && this.brightnessbelow == other.brightnessbelow && this.colorbelow.ToInt() == other.colorbelow.ToInt() &&
            this.disablelighting == other.disablelighting && this.restrictlighting == other.restrictlighting &&
            this.resetlighting == other.resetlighting);
 }
        public void Update()
        {
            // Create ceiling glow effect?
            data.CeilingGlow = GetGlowData(false);
            if (data.CeilingGlow != null)
            {
                // Create ceiling level?
                if (ceillevel == null)
                {
                    ceillevel = new SectorLevel(data.Ceiling)
                    {
                        type = SectorLevelType.Glow, disablelighting = true
                    };
                    data.AddSectorLevel(ceillevel);
                }

                // Update ceiling level
                ceillevel.brightnessbelow = -1;                 // We need this plane for clipping only,
                ceillevel.color           = 0;                  // so we need to reset all shading and coloring
                ceillevel.plane           = data.Ceiling.plane;
                ceillevel.plane.Offset   -= data.CeilingGlow.Height;
                data.CeilingGlowPlane     = ceillevel.plane;
            }

            // Create floor glow effect?
            data.FloorGlow = GetGlowData(true);
            if (data.FloorGlow != null)
            {
                // Create floor level?
                if (floorlevel == null)
                {
                    floorlevel = new SectorLevel(data.Floor)
                    {
                        type = SectorLevelType.Glow, disablelighting = true
                    };
                    data.AddSectorLevel(floorlevel);
                }

                // Update floor level
                floorlevel.plane         = data.Floor.plane.GetInverted();
                floorlevel.plane.Offset += data.FloorGlow.Height;

                if (floorlevel.plane.Offset < data.Ceiling.plane.Offset)
                {
                    floorlevel.brightnessbelow = -1;                     // We need this plane for clipping only,
                    floorlevel.color           = 0;                      // so we need to reset all shading and coloring
                    floorlevel.colorbelow      = new PixelColor(0, 0, 0, 0);
                }
                else
                {
                    // If glow plane is above real ceiling, apply ceiling colouring
                    floorlevel.brightnessbelow = data.Ceiling.brightnessbelow;
                    floorlevel.color           = data.Ceiling.color;
                    floorlevel.colorbelow      = data.Ceiling.colorbelow;
                }

                data.FloorGlowPlane = floorlevel.plane;
            }
        }
Beispiel #4
0
 // Copy properties
 public void CopyProperties(SectorLevel target)
 {
     target.sector           = this.sector;
     target.type             = this.type;
     target.lighttype        = this.lighttype;      //mxd
     target.plane            = this.plane;
     target.alpha            = this.alpha;
     target.color            = this.color;
     target.brightnessbelow  = this.brightnessbelow;
     target.colorbelow       = this.colorbelow;
     target.affectedbyglow   = this.affectedbyglow;   //mxd
     target.disablelighting  = this.disablelighting;  //mxd
     target.restrictlighting = this.restrictlighting; //mxd
     target.resetlighting    = this.resetlighting;    //mxd
     target.splitsides       = this.splitsides;       //mxd
 }
Beispiel #5
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);
        }
Beispiel #6
0
        // This returns the level above the given point
        public SectorLevel GetLevelAbove(Vector3D pos)
        {
            SectorLevel found = null;
            double      dist  = double.MaxValue;

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

            return(found);
        }
Beispiel #7
0
        //mxd. This returns the level above the given point or the level given point is located on
        public SectorLevel GetLevelAboveOrAt(Vector3D pos)
        {
            SectorLevel found = null;
            float       dist  = float.MaxValue;

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

            return(found);
        }
Beispiel #8
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);
        }
Beispiel #9
0
        // This returns the floor below the given point
        public SectorLevel GetFloorBelow(Vector3D pos)
        {
            SectorLevel found = null;
            double      dist  = double.MaxValue;

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

            return(found);
        }
Beispiel #10
0
        //mxd
        private int GetLevelColor(SectorLevel src, SectorLevel target)
        {
            PixelColor brightness;

            if (lightfloorabsolute && target == floor)
            {
                brightness = PixelColor.FromInt(mode.CalculateBrightness(lightfloor));
            }
            else if (lightceilingabsolute && target == ceiling)
            {
                brightness = PixelColor.FromInt(mode.CalculateBrightness(lightceiling));
            }
            else
            {
                brightness = PixelColor.FromInt(mode.CalculateBrightness(src.brightnessbelow));
            }

            PixelColor color = PixelColor.Modulate(src.colorbelow, brightness);

            return(color.WithAlpha(255).ToInt());
        }
        // 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);

            // Create top level?
            if (toplevel == null)
            {
                toplevel = new SectorLevel(sd.Ceiling);
                data.AddSectorLevel(toplevel);
            }

            // Update top level
            sd.Ceiling.CopyProperties(toplevel);
            toplevel.lighttype = (LightLevelType)General.Clamp(linedef.Args[1], 0, 2);             //mxd
            toplevel.type      = SectorLevelType.Light;

            //mxd. Create bottom level?
            if (toplevel.lighttype == LightLevelType.TYPE1)
            {
                // Create bottom level? Skip this step if there's a different light level between toplevel and bottomlevel
                if (bottomlevel == null)
                {
                    bottomlevel = new SectorLevel(data.Ceiling);
                    data.AddSectorLevel(bottomlevel);
                }

                // Update bottom level
                data.Ceiling.CopyProperties(bottomlevel);
                bottomlevel.type      = SectorLevelType.Light;
                bottomlevel.lighttype = LightLevelType.TYPE1_BOTTOM;
                bottomlevel.plane     = sd.Floor.plane.GetInverted();
            }
        }
Beispiel #12
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.floorbase         = new SectorLevel(sector, SectorLevelType.Floor);   //mxd
            this.ceiling           = new SectorLevel(sector, SectorLevelType.Ceiling);
            this.ceilingbase       = new SectorLevel(sector, SectorLevelType.Ceiling); //mxd
            this.glowingflateffect = new EffectGlowingFlat(this);                      //mxd

            // Add ceiling and floor
            lightlevels.Add(floor);
            lightlevels.Add(ceiling);

            BasicSetup();
        }
Beispiel #13
0
 public virtual bool Setup(SectorLevel level, Effect3DFloor extrafloor)
 {
     this.level      = level;
     this.extrafloor = extrafloor;
     return(false);
 }
Beispiel #14
0
        internal static float GetLowerThingZ(BaseVisualMode mode, SectorData sd, VisualThing thing)
        {
            Vector3D pos         = thing.Thing.Position;
            float    thingheight = thing.Thing.Height;
            bool     absolute    = thing.Info.AbsoluteZ;
            bool     hangs       = thing.Info.Hangs;

            if (absolute && hangs)
            {
                General.Interface.DisplayStatus(StatusType.Warning, "Sorry, can't have both 'absolute' and 'hangs' flags...");
                return(pos.z);
            }

            // Get things, which bounding boxes intersect with target thing
            IEnumerable <Thing> intersectingthings = GetIntersectingThings(mode, thing.Thing);

            float fz = (absolute ? 0 : sd.Floor.plane.GetZ(pos));
            float cz = sd.Ceiling.plane.GetZ(pos);

            if (hangs)
            {
                // Transform to floor-aligned position
                Vector3D floorpos    = new Vector3D(pos, (cz - fz) - pos.z - thingheight);
                float    lowertingz  = GetNextLowerThingZ(mode, intersectingthings, floorpos.z, thingheight);
                float    lowerfloorz = float.MaxValue;

                // Do it only when there are extrafloors
                if (sd.LightLevels.Count > 2)
                {
                    // Unlike sd.ExtraFloors, these are sorted by height
                    for (int i = sd.LightLevels.Count - 1; i > -1; i--)
                    {
                        SectorLevel level = sd.LightLevels[i];
                        if (level.type == SectorLevelType.Light || level.type == SectorLevelType.Glow)
                        {
                            continue;                                                                                                   // Skip lights and glows
                        }
                        float z = level.plane.GetZ(floorpos) - fz;
                        if (level.type == SectorLevelType.Ceiling)
                        {
                            z -= thingheight;
                        }
                        if (z < floorpos.z)
                        {
                            lowerfloorz = z;
                            break;
                        }
                    }
                }

                float floorz = cz - fz;                 // Floor height when counted from ceiling

                if (lowerfloorz != float.MaxValue && lowertingz != float.MinValue)
                {
                    // Transform back to ceiling-aligned position
                    return(cz - fz - Math.Min(Math.Max(lowerfloorz, lowertingz), floorz) - thingheight);
                }

                if (lowerfloorz != float.MaxValue)
                {
                    // Transform back to ceiling-aligned position
                    return(cz - fz - Math.Min(lowerfloorz, floorz) - thingheight);
                }

                if (lowertingz != float.MinValue)
                {
                    // Transform back to ceiling-aligned position
                    return(cz - fz - Math.Min(lowertingz, floorz) - thingheight);
                }

                return(floorz - thingheight);                // Align to real floor
            }
            else
            {
                float lowertingz  = GetNextLowerThingZ(mode, intersectingthings, (absolute ? pos.z - fz : pos.z), thingheight);
                float lowerfloorz = float.MaxValue;

                // Do it only when there are extrafloors
                if (sd.LightLevels.Count > 2)
                {
                    // Unlike sd.ExtraFloors, these are sorted by height
                    for (int i = sd.LightLevels.Count - 1; i > -1; i--)
                    {
                        SectorLevel level = sd.LightLevels[i];
                        if (level.type == SectorLevelType.Light || level.type == SectorLevelType.Glow)
                        {
                            continue;                                                                                                   // Skip lights and glows
                        }
                        float z = level.plane.GetZ(pos) - fz;
                        if (level.type == SectorLevelType.Ceiling)
                        {
                            z -= thingheight;
                        }
                        if (z < pos.z)
                        {
                            lowerfloorz = z;
                            break;
                        }
                    }
                }

                float floorz   = sd.Floor.plane.GetZ(pos);               // Floor-aligned relative target thing z
                float floorpos = 0;

                if (lowerfloorz != float.MaxValue && lowertingz != float.MinValue)
                {
                    floorpos = Math.Max(Math.Max(lowerfloorz, lowertingz), floorz);
                }
                if (lowerfloorz != float.MaxValue)
                {
                    floorpos = Math.Max(lowerfloorz, floorz);
                }
                if (lowertingz != float.MinValue)
                {
                    floorpos = Math.Max(lowertingz, floorz);
                }

                return(absolute ? floorpos + floorz : floorpos);                  // Convert to absolute position if necessary
            }
        }
Beispiel #15
0
 // Copy constructor
 public SectorLevel(SectorLevel source)
 {
     source.CopyProperties(this);
 }
Beispiel #16
0
        // This builds the thing geometry. Returns false when nothing was created.
        public bool Setup()
        {
            // Find the sector in which the thing resides
            Thing.DetermineSector(mode.BlockMap);

            //mxd. If the thing is inside a sector, apply DECORATE/UDMF alpha/renderstyle overrides
            byte alpha = 255;

            if (Thing.Sector != null)
            {
                string renderstyle = info.RenderStyle.ToLowerInvariant();
                alpha = info.AlphaByte;

                if (General.Map.UDMF)
                {
                    if (Thing.IsFlagSet("translucent"))
                    {
                        renderstyle = "translucent";
                        alpha       = 64;
                    }
                    else if (Thing.IsFlagSet("invisible"))
                    {
                        renderstyle = "none";
                        alpha       = 0;
                    }
                    else if (Thing.Fields.ContainsKey("renderstyle"))
                    {
                        renderstyle = Thing.Fields.GetValue("renderstyle", renderstyle).ToLowerInvariant();
                    }

                    if ((renderstyle == "add" || renderstyle == "translucent" || renderstyle == "subtract" || renderstyle == "translucentstencil") &&
                        Thing.Fields.ContainsKey("alpha"))
                    {
                        alpha = (byte)(General.Clamp(Thing.Fields.GetValue("alpha", info.Alpha), 0.0, 1.0) * 255.0);
                    }
                    else if (renderstyle == "soultrans")
                    {
                        // Lost Soul trasparency is controlled by a CVAR (see https://zdoom.org/wiki/CVARs:Display#transsouls), let's use the default 0.75 here
                        alpha = 192;
                    }
                    else if (renderstyle == "shadow")
                    {
                        alpha        = 76;                  // about 0.3
                        stencilColor = PixelColor.FromInt(PixelColor.INT_BLACK);
                    }

                    if (renderstyle.EndsWith("stencil"))
                    {
                        stencilColor   = PixelColor.FromInt(UniFields.GetInteger(Thing.Fields, "fillcolor", 0));
                        stencilColor.a = 255; // 0xFF alpha means nothing was read. 0x00 alpha means there was a valid fillcolor.
                    }
                    else if (renderstyle != "shadow")
                    {
                        stencilColor.a = 0;
                    }
                }
                else if (General.Map.HEXEN)
                {
                    if (Thing.IsFlagSet("2048"))
                    {
                        renderstyle = "translucent";
                        alpha       = 64;
                    }
                    else if (Thing.IsFlagSet("4096"))
                    {
                        renderstyle = "none";
                        alpha       = 0;
                    }
                }

                // Set appropriate RenderPass
                switch (renderstyle)
                {
                case "translucent":
                case "subtract":
                case "soultrans":
                case "translucentstencil":
                case "shadow":
                    RenderPass = RenderPass.Alpha;
                    break;

                case "add":
                case "addstencil":
                    RenderPass = RenderPass.Additive;
                    break;

                case "none":
                    RenderPass = RenderPass.Mask;
                    alpha      = 0;
                    break;

                // Many render styles are not supported yet...
                default:
                    RenderPass = RenderPass.Mask;
                    alpha      = 255;
                    break;
                }
            }

            int sectorcolor = new PixelColor(alpha, 255, 255, 255).ToInt();

            fogfactor = 0f;             //mxd

            //mxd. Check thing size
            float thingradius = Thing.Size;         // Thing.Size has ThingRadius arg override applied

            thingheight = Thing.Height;             // Thing.Height has ThingHeight arg override applied

            if (thingradius < 0.1f || thingheight < 0.1f)
            {
                thingradius = FIXED_RADIUS;
                thingheight = FIXED_RADIUS;
                sizeless    = true;
            }
            else
            {
                sizeless = false;
            }

            if (Thing.Sector != null)
            {
                SectorData sd    = mode.GetSectorData(Thing.Sector);
                Plane      floor = sd.Floor.plane;            //mxd

                if (!info.Bright)
                {
                    Vector3D    thingpos = new Vector3D(Thing.Position.x, Thing.Position.y, Thing.Position.z + sd.Floor.plane.GetZ(Thing.Position));
                    SectorLevel level    = sd.GetLevelAboveOrAt(thingpos);

                    //mxd. Let's use point on floor plane instead of Thing.Sector.FloorHeight;
                    if (nointeraction && level == null && sd.LightLevels.Count > 0)
                    {
                        level = sd.LightLevels[sd.LightLevels.Count - 1];
                    }

                    //mxd. Use the light level of the highest surface when a thing is above highest sector level.
                    if (level != null)
                    {
                        // TECH: In GZDoom, ceiling glow doesn't affect thing brightness
                        // Use sector brightness for color shading
                        int brightness = level.brightnessbelow;

                        //mxd. Apply lightfloor value
                        // According to Graf, this is incorrect behaviour...
                        // TECH: In (G)ZDoom, this is ignored when ceiling texture is sky or a thing is below a 3D floor
                        // It's probably more involved than this, but for now let's do it only when there are no 3d floors in Thing.Sector...

                        /*if(General.Map.UDMF && sd.LightLevels.Count == 2 && Thing.Sector.CeilTexture != General.Map.Config.SkyFlatName)
                         * {
                         *      if(sd.Sector.Fields.GetValue("lightfloorabsolute", false))
                         *              brightness = UniFields.GetInteger(sd.Sector.Fields, "lightfloor");
                         *      else
                         *              brightness += UniFields.GetInteger(sd.Sector.Fields, "lightfloor");
                         * }*/

                        // Level is glowing
                        if (level.affectedbyglow && level.type == SectorLevelType.Floor)
                        {
                            // Extrafloor glow doesn't affect thing brightness
                            if (level.sector == Thing.Sector)
                            {
                                double planez = level.plane.GetZ(thingpos);

                                // Get glow brightness
                                int         glowbrightness = sd.FloorGlow.Brightness / 2;
                                SectorLevel nexthigher     = sd.GetLevelAbove(new Vector3D(thingpos, planez));

                                // Interpolate thing brightness between glow and regular ones
                                if (nexthigher != null)
                                {
                                    double higherz = nexthigher.plane.GetZ(thingpos);
                                    double delta   = General.Clamp(1.0f - (thingpos.z - planez) / (higherz - planez), 0f, 1f);
                                    brightness = (int)((glowbrightness + level.sector.Brightness / 2) * delta + nexthigher.sector.Brightness * (1.0f - delta));
                                }
                            }
                        }
                        // Level below this one is glowing. Only possible for floor glow(?)
                        else if (level.type == SectorLevelType.Glow)
                        {
                            // Interpolate thing brightness between glow and regular ones
                            if (sd.Floor != null && sd.FloorGlow != null)
                            {
                                // Get glow brightness
                                double glowz  = level.plane.GetZ(thingpos);
                                double floorz = floor.GetZ(thingpos);
                                double delta  = General.Clamp((thingpos.z - floorz) / (glowz - floorz), 0f, 1f);

                                brightness = (int)((sd.FloorGlow.Brightness / 2 + sd.Floor.sector.Brightness / 2) * (1.0f - delta) + sd.Floor.sector.Brightness * delta);
                            }
                        }

                        PixelColor areabrightness = PixelColor.FromInt(mode.CalculateBrightness(brightness));
                        PixelColor areacolor      = PixelColor.Modulate(level.colorbelow, areabrightness);

                        // [ZZ] if sector is using Doom64 lighting, apply thing color here.
                        sectorcolor = PixelColor.Modulate(sd.ColorSprites, areacolor).WithAlpha(alpha).ToInt();

                        //mxd. Calculate fogfactor
                        fogfactor = VisualGeometry.CalculateFogFactor(level.sector, brightness);
                    }
                }
                //TECH: even Bright Thing frames are affected by custom fade...
                else
                {
                    Vector3D    thingpos = new Vector3D(Thing.Position.x, Thing.Position.y, Thing.Position.z + sd.Floor.plane.GetZ(Thing.Position));
                    SectorLevel level    = sd.GetLevelAboveOrAt(thingpos);

                    if (level != null && level.sector.FogMode > SectorFogMode.CLASSIC)
                    {
                        //mxd. Calculate fogfactor
                        fogfactor = VisualGeometry.CalculateFogFactor(level.sector, level.brightnessbelow);
                    }
                }
            }

            //mxd. Create verts for all sprite angles
            WorldVertex[][] allverts   = new WorldVertex[info.SpriteFrame.Length][];
            Vector2D[]      alloffsets = new Vector2D[info.SpriteFrame.Length];
            base.textures = new ImageData[info.SpriteFrame.Length];
            isloaded      = true;

            for (int i = 0; i < sprites.Length; i++)
            {
                Vector2D offsets = new Vector2D();

                // Check if the texture is loaded
                ImageData sprite = sprites[i];
                if (!sprite.IsImageLoaded && !sprite.LoadFailed)
                {
                    sprite.LoadImageNow();
                }
                if (sprite.IsImageLoaded)
                {
                    base.textures[i] = sprite;

                    // Determine sprite size and offset
                    float        radius    = sprite.ScaledWidth * 0.5f;
                    float        height    = sprite.ScaledHeight;
                    ISpriteImage spriteimg = sprite as ISpriteImage;
                    if (spriteimg != null)
                    {
                        offsets.x = radius - spriteimg.OffsetX;
                        offsets.y = spriteimg.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;
                    offsets.x *= info.SpriteScale.Width;
                    offsets.y *= info.SpriteScale.Height;

                    // Make vertices
                    WorldVertex[] verts = new WorldVertex[6];

                    //mxd. Sprite mirroring
                    float ul = (info.SpriteFrame[i].Mirror ? 1f : 0f);
                    float ur = (info.SpriteFrame[i].Mirror ? 0f : 1f);

                    if (sizeless)                    //mxd
                    {
                        float hh = height / 2;
                        verts[0] = new WorldVertex((float)(-radius + offsets.x), 0.0f, (float)(offsets.y - hh), sectorcolor, ul, 1.0f);
                        verts[1] = new WorldVertex((float)(-radius + offsets.x), 0.0f, (float)(hh + offsets.y), sectorcolor, ul, 0.0f);
                        verts[2] = new WorldVertex((float)(+radius + offsets.x), 0.0f, (float)(hh + offsets.y), sectorcolor, ur, 0.0f);
                        verts[3] = verts[0];
                        verts[4] = verts[2];
                        verts[5] = new WorldVertex((float)(+radius + offsets.x), 0.0f, (float)(offsets.y - hh), sectorcolor, ur, 1.0f);
                    }
                    else
                    {
                        verts[0] = new WorldVertex((float)(-radius + offsets.x), 0.0f, (float)offsets.y, sectorcolor, ul, 1.0f);
                        verts[1] = new WorldVertex((float)(-radius + offsets.x), 0.0f, (float)(height + offsets.y), sectorcolor, ul, 0.0f);
                        verts[2] = new WorldVertex((float)(+radius + offsets.x), 0.0f, (float)(height + offsets.y), sectorcolor, ur, 0.0f);
                        verts[3] = verts[0];
                        verts[4] = verts[2];
                        verts[5] = new WorldVertex((float)(+radius + offsets.x), 0.0f, (float)offsets.y, sectorcolor, ur, 1.0f);
                    }
                    allverts[i] = verts;
                }
                else
                {
                    isloaded         = false;
                    base.textures[i] = sprite;

                    // Determine sprite size
                    float radius = Math.Min(thingradius, thingheight / 2f);
                    float height = Math.Min(thingradius * 2f, thingheight);

                    //mxd. Determine sprite offsets
                    offsets.x = radius;
                    offsets.y = height / 2;

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

                //mxd. Store offsets
                alloffsets[i] = offsets;
            }

            //mxd
            SetVertices(allverts, alloffsets /*, floor, ceiling*/);

            // Determine position
            Vector3D pos = Thing.Position;

            if (Thing.Type == 9501)
            {
                if (Thing.Sector != null)                //mxd
                {
                    // 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)
            {
                if (Thing.Sector != null)                //mxd
                {
                    // 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);
                    double     maxz = sd.Ceiling.plane.GetZ(Thing.Position) - info.Height;
                    pos.z = maxz;

                    if (Thing.Position.z > 0 || nointeraction)
                    {
                        pos.z -= Thing.Position.z;
                    }

                    // Check if below floor
                    if (!nointeraction)
                    {
                        double minz = sd.Floor.plane.GetZ(Thing.Position);
                        if (pos.z < minz)
                        {
                            pos.z = Math.Min(minz, maxz);
                        }
                    }
                }
            }
            else
            {
                // Stand on floor
                if (Thing.Sector != null)
                {
                    SectorData sd   = mode.GetSectorData(Thing.Sector);
                    double     minz = sd.Floor.plane.GetZ(Thing.Position);
                    pos.z = minz;

                    if (Thing.Position.z > 0 || nointeraction)
                    {
                        pos.z += Thing.Position.z;
                    }

                    // Check if above ceiling
                    if (!nointeraction)
                    {
                        double maxz = sd.Ceiling.plane.GetZ(Thing.Position) - info.Height;
                        if (pos.z > maxz)
                        {
                            pos.z = Math.Max(minz, maxz);
                        }
                    }
                }
            }

            // Apply settings
            SetPosition(pos);
            SetCageColor(Thing.Color);

            // Keep info for object picking
            cageradius2 = thingradius * Angle2D.SQRT2;
            cageradius2 = cageradius2 * cageradius2;
            pos2d       = pos;

            if (sizeless)            //mxd
            {
                boxp1 = new Vector3D(pos.x - thingradius, pos.y - thingradius, pos.z - thingradius / 2);
                boxp2 = new Vector3D(pos.x + thingradius, pos.y + thingradius, pos.z + thingradius / 2);
            }
            else
            {
                boxp1 = new Vector3D(pos.x - thingradius, pos.y - thingradius, pos.z);
                boxp2 = new Vector3D(pos.x + thingradius, pos.y + thingradius, pos.z + thingheight);
            }

            // Done
            changed = false;
            return(true);
        }
        // This builds the thing geometry. Returns false when nothing was created.
        public bool Setup()
        {
            // Find the sector in which the thing resides
            Thing.DetermineSector(mode.BlockMap);

            //mxd. If the thing is inside a sector, apply DECORATE/UDMF alpha/renderstyle overrides
            byte alpha = 255;

            if (Thing.Sector != null)
            {
                string renderstyle = info.RenderStyle;
                alpha = info.AlphaByte;

                if (General.Map.UDMF)
                {
                    if (Thing.IsFlagSet("translucent"))
                    {
                        renderstyle = "translucent";
                        alpha       = 64;
                    }
                    else if (Thing.IsFlagSet("invisible"))
                    {
                        renderstyle = "none";
                        alpha       = 0;
                    }
                    else if (Thing.Fields.ContainsKey("renderstyle"))
                    {
                        renderstyle = Thing.Fields.GetValue("renderstyle", renderstyle);
                    }

                    if ((renderstyle == "add" || renderstyle == "translucent" || renderstyle == "subtract" || renderstyle == "stencil") &&
                        Thing.Fields.ContainsKey("alpha"))
                    {
                        alpha = (byte)(General.Clamp(Thing.Fields.GetValue("alpha", info.Alpha), 0f, 1f) * 255);
                    }
                }
                else if (General.Map.HEXEN)
                {
                    if (Thing.IsFlagSet("2048"))
                    {
                        renderstyle = "translucent";
                        alpha       = 64;
                    }
                    else if (Thing.IsFlagSet("4096"))
                    {
                        renderstyle = "none";
                        alpha       = 0;
                    }
                }

                // Set appropriate RenderPass
                switch (renderstyle)
                {
                case "translucent":
                case "subtract":
                case "stencil":
                    RenderPass = RenderPass.Alpha;
                    break;

                case "add":
                    RenderPass = RenderPass.Additive;
                    break;

                case "none":
                    RenderPass = RenderPass.Mask;
                    alpha      = 0;
                    break;

                // Many render styles are not supported yet...
                default:
                    RenderPass = RenderPass.Mask;
                    alpha      = 255;
                    break;
                }
            }

            // Don't bother when alpha is unchanged, unless Additive RenderStyle is used
            if (RenderPass != RenderPass.Additive && alpha == 255)
            {
                RenderPass = RenderPass.Mask;
            }

            int sectorcolor = new PixelColor(alpha, 255, 255, 255).ToInt();

            fogfactor = 0f;             //mxd

            //mxd. Check thing size
            float thingradius = Thing.Size;         // Thing.Size has ThingRadius arg override applied

            thingheight = Thing.Height;             // Thing.Height has ThingHeight arg override applied

            if (thingradius < 0.1f || thingheight < 0.1f)
            {
                thingradius = FIXED_RADIUS;
                thingheight = FIXED_RADIUS;
                sizeless    = true;
            }
            else
            {
                sizeless = false;
            }

            Plane floor   = new Plane();           //mxd
            Plane ceiling = new Plane();           //mxd

            if (Thing.Sector != null)
            {
                SectorData sd = mode.GetSectorData(Thing.Sector);
                floor   = sd.Floor.plane;               //mxd
                ceiling = sd.Ceiling.plane;             //mxd

                if (!info.Bright)
                {
                    Vector3D    thingpos = new Vector3D(Thing.Position.x, Thing.Position.y, Thing.Position.z + sd.Floor.plane.GetZ(Thing.Position));
                    SectorLevel level    = sd.GetLevelAboveOrAt(thingpos);

                    //mxd. Let's use point on floor plane instead of Thing.Sector.FloorHeight;
                    if (nointeraction && level == null && sd.LightLevels.Count > 0)
                    {
                        level = sd.LightLevels[sd.LightLevels.Count - 1];
                    }

                    //mxd. Use the light level of the highest surface when a thing is above highest sector level.
                    if (level != null)
                    {
                        // TECH: In GZDoom, ceiling glow doesn't affect thing brightness
                        // Use sector brightness for color shading
                        int brightness = level.brightnessbelow;

                        // Level is glowing
                        if (level.affectedbyglow && level.type == SectorLevelType.Floor)
                        {
                            // Extrafloor glow doesn't affect thing brightness
                            if (level.sector == Thing.Sector)
                            {
                                float planez = level.plane.GetZ(thingpos);

                                // Get glow brightness
                                int         glowbrightness = sd.FloorGlow.Brightness / 2;
                                SectorLevel nexthigher     = sd.GetLevelAbove(new Vector3D(thingpos, planez));

                                // Interpolate thing brightness between glow and regular ones
                                if (nexthigher != null)
                                {
                                    float higherz = nexthigher.plane.GetZ(thingpos);
                                    float delta   = General.Clamp(1.0f - (thingpos.z - planez) / (higherz - planez), 0f, 1f);
                                    brightness = (int)((glowbrightness + level.sector.Brightness / 2) * delta + nexthigher.sector.Brightness * (1.0f - delta));
                                }
                            }
                        }
                        // Level below this one is glowing. Only possible for floor glow(?)
                        else if (level.type == SectorLevelType.Glow)
                        {
                            // Interpolate thing brightness between glow and regular ones
                            if (sd.Floor != null && sd.FloorGlow != null)
                            {
                                // Get glow brightness
                                float glowz  = level.plane.GetZ(thingpos);
                                float floorz = floor.GetZ(thingpos);
                                float delta  = General.Clamp((thingpos.z - floorz) / (glowz - floorz), 0f, 1f);

                                brightness = (int)((sd.FloorGlow.Brightness / 2 + sd.Floor.sector.Brightness / 2) * (1.0f - delta) + sd.Floor.sector.Brightness * delta);
                            }
                        }

                        PixelColor areabrightness = PixelColor.FromInt(mode.CalculateBrightness(brightness));
                        PixelColor areacolor      = PixelColor.Modulate(level.colorbelow, areabrightness);
                        sectorcolor = areacolor.WithAlpha(alpha).ToInt();

                        //mxd. Calculate fogfactor
                        fogfactor = VisualGeometry.CalculateFogFactor(level.sector.FogMode, brightness);
                    }
                }
                //TECH: even Bright Thing frames are affected by custom fade...
                else
                {
                    Vector3D    thingpos = new Vector3D(Thing.Position.x, Thing.Position.y, Thing.Position.z + sd.Floor.plane.GetZ(Thing.Position));
                    SectorLevel level    = sd.GetLevelAboveOrAt(thingpos);

                    if (level != null && level.sector.FogMode > SectorFogMode.CLASSIC)
                    {
                        //mxd. Calculate fogfactor
                        fogfactor = VisualGeometry.CalculateFogFactor(level.sector.FogMode, level.brightnessbelow);
                    }
                }
            }

            //mxd. Create verts for all sprite angles
            WorldVertex[][] allverts   = new WorldVertex[info.SpriteFrame.Length][];
            Vector2D[]      alloffsets = new Vector2D[info.SpriteFrame.Length];
            base.textures = new ImageData[info.SpriteFrame.Length];
            isloaded      = true;

            for (int i = 0; i < sprites.Length; i++)
            {
                Vector2D offsets = new Vector2D();

                // Check if the texture is loaded
                ImageData sprite = sprites[i];
                sprite.LoadImage();
                if (sprite.IsImageLoaded)
                {
                    base.textures[i] = sprite;

                    // Determine sprite size and offset
                    float        radius    = sprite.ScaledWidth * 0.5f;
                    float        height    = sprite.ScaledHeight;
                    ISpriteImage spriteimg = sprite as ISpriteImage;
                    if (spriteimg != null)
                    {
                        offsets.x = radius - spriteimg.OffsetX;
                        offsets.y = spriteimg.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;
                    offsets.x *= info.SpriteScale.Width;
                    offsets.y *= info.SpriteScale.Height;

                    // Make vertices
                    WorldVertex[] verts = new WorldVertex[6];

                    //mxd. Sprite mirroring
                    float ul = (info.SpriteFrame[i].Mirror ? 1f : 0f);
                    float ur = (info.SpriteFrame[i].Mirror ? 0f : 1f);

                    if (sizeless)                    //mxd
                    {
                        float hh = height / 2;
                        verts[0] = new WorldVertex(-radius + offsets.x, 0.0f, offsets.y - hh, sectorcolor, ul, 1.0f);
                        verts[1] = new WorldVertex(-radius + offsets.x, 0.0f, hh + offsets.y, sectorcolor, ul, 0.0f);
                        verts[2] = new WorldVertex(+radius + offsets.x, 0.0f, hh + offsets.y, sectorcolor, ur, 0.0f);
                        verts[3] = verts[0];
                        verts[4] = verts[2];
                        verts[5] = new WorldVertex(+radius + offsets.x, 0.0f, offsets.y - hh, sectorcolor, ur, 1.0f);
                    }
                    else
                    {
                        verts[0] = new WorldVertex(-radius + offsets.x, 0.0f, offsets.y, sectorcolor, ul, 1.0f);
                        verts[1] = new WorldVertex(-radius + offsets.x, 0.0f, height + offsets.y, sectorcolor, ul, 0.0f);
                        verts[2] = new WorldVertex(+radius + offsets.x, 0.0f, height + offsets.y, sectorcolor, ur, 0.0f);
                        verts[3] = verts[0];
                        verts[4] = verts[2];
                        verts[5] = new WorldVertex(+radius + offsets.x, 0.0f, offsets.y, sectorcolor, ur, 1.0f);
                    }
                    allverts[i] = verts;
                }
                else
                {
                    isloaded         = false;
                    base.textures[i] = General.Map.Data.Hourglass3D;

                    // Determine sprite size
                    float radius = Math.Min(thingradius, thingheight / 2f);
                    float height = Math.Min(thingradius * 2f, thingheight);

                    //mxd. Determine sprite offsets
                    offsets.x = radius;
                    offsets.y = height / 2;

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

                //mxd. Store offsets
                alloffsets[i] = offsets;
            }

            //mxd
            SetVertices(allverts, alloffsets /*, floor, ceiling*/);

            // Determine position
            Vector3D pos = Thing.Position;

            if (Thing.Type == 9501)
            {
                if (Thing.Sector != null)                //mxd
                {
                    // 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)
            {
                if (Thing.Sector != null)                //mxd
                {
                    // 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);
                    float      maxz = sd.Ceiling.plane.GetZ(Thing.Position) - info.Height;
                    pos.z = maxz;

                    if (Thing.Position.z > 0 || nointeraction)
                    {
                        pos.z -= Thing.Position.z;
                    }

                    // Check if below floor
                    if (!nointeraction)
                    {
                        float minz = sd.Floor.plane.GetZ(Thing.Position);
                        if (pos.z < minz)
                        {
                            pos.z = Math.Min(minz, maxz);
                        }
                    }
                }
            }
            else
            {
                // Stand on floor
                if (Thing.Sector != null)
                {
                    SectorData sd   = mode.GetSectorData(Thing.Sector);
                    float      minz = sd.Floor.plane.GetZ(Thing.Position);
                    pos.z = minz;

                    if (Thing.Position.z > 0 || nointeraction)
                    {
                        pos.z += Thing.Position.z;
                    }

                    // Check if above ceiling
                    if (!nointeraction)
                    {
                        float maxz = sd.Ceiling.plane.GetZ(Thing.Position) - info.Height;
                        if (pos.z > maxz)
                        {
                            pos.z = Math.Max(minz, maxz);
                        }
                    }
                }
            }

            // Apply settings
            SetPosition(pos);
            SetCageColor(Thing.Color);

            // Keep info for object picking
            cageradius2 = thingradius * Angle2D.SQRT2;
            cageradius2 = cageradius2 * cageradius2;
            pos2d       = pos;

            if (sizeless)            //mxd
            {
                boxp1 = new Vector3D(pos.x - thingradius, pos.y - thingradius, pos.z - thingradius / 2);
                boxp2 = new Vector3D(pos.x + thingradius, pos.y + thingradius, pos.z + thingradius / 2);
            }
            else
            {
                boxp1 = new Vector3D(pos.x - thingradius, pos.y - thingradius, pos.z);
                boxp2 = new Vector3D(pos.x + thingradius, pos.y + thingradius, pos.z + thingheight);
            }

            // Done
            changed = false;
            return(true);
        }
Beispiel #18
0
 // This builds the geometry. Returns false when no geometry created.
 public override bool Setup(SectorLevel level, Effect3DFloor extrafloor)
 {
     return(Setup(level, extrafloor, innerside));
 }
Beispiel #19
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();
            }

            //mxd. Do complicated light level shenanigans only when there are extrafloors
            if (lightlevels.Count > 2)
            {
                // Sort the levels
                SectorLevelComparer comparer = new SectorLevelComparer(sector);
                lightlevels.Sort(0, lightlevels.Count, 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.
                SectorLevel stored = ceilingbase;

                //mxd. Special cases...
                if (lightlevels[lightlevels.Count - 1].disablelighting)
                {
                    lightlevels[lightlevels.Count - 1].colorbelow      = stored.colorbelow;
                    lightlevels[lightlevels.Count - 1].brightnessbelow = stored.brightnessbelow;
                    lightlevels[lightlevels.Count - 1].color           = GetLevelColor(stored, lightlevels[lightlevels.Count - 1]);
                }

                //mxd. Cast light properties from top to bottom
                for (int i = lightlevels.Count - 2; i >= 0; i--)
                {
                    SectorLevel l  = lightlevels[i];
                    SectorLevel pl = lightlevels[i + 1];

                    // Glow levels don't cast light
                    if (pl.type == SectorLevelType.Glow && lightlevels.Count > i + 2)
                    {
                        pl = lightlevels[i + 2];
                    }

                    if (l.lighttype == LightLevelType.TYPE1)
                    {
                        stored = pl;
                    }
                    // Use stored light params when "disablelighting" flag is set
                    else if (l.disablelighting)
                    {
                        l.colorbelow      = stored.colorbelow;
                        l.brightnessbelow = stored.brightnessbelow;
                        l.color           = GetLevelColor(stored, l);
                    }
                    else if (l.restrictlighting)
                    {
                        if (!pl.restrictlighting && pl != ceiling)
                        {
                            stored = pl;
                        }
                        l.color = GetLevelColor(stored, l);

                        // This is the bottom side of extrafloor with "restrict lighting" flag. Make it cast stored light props.
                        if (l.type == SectorLevelType.Ceiling)
                        {
                            // Special case: 2 intersecting extrafloors with "restrictlighting" flag...
                            if (pl.restrictlighting && pl.type == SectorLevelType.Floor && pl.sector.Index != l.sector.Index)
                            {
                                // Use light and color settings from previous layer
                                l.colorbelow      = pl.colorbelow;
                                l.brightnessbelow = pl.brightnessbelow;
                                l.color           = GetLevelColor(pl, l);

                                // Also colorize previous layer using next higher level color
                                if (i + 2 < lightlevels.Count)
                                {
                                    pl.color = GetLevelColor(lightlevels[i + 2], pl);
                                }
                            }
                            else
                            {
                                l.colorbelow      = stored.colorbelow;
                                l.brightnessbelow = stored.brightnessbelow;
                            }
                        }
                    }
                    // Bottom TYPE1 border requires special handling...
                    else if (l.lighttype == LightLevelType.TYPE1_BOTTOM)
                    {
                        // Use brightness and color from previous light level when it's between TYPE1 and TYPE1_BOTTOM levels
                        if (pl.type == SectorLevelType.Light && pl.lighttype != LightLevelType.TYPE1)
                        {
                            l.brightnessbelow = pl.brightnessbelow;
                            l.colorbelow      = pl.colorbelow;
                        }
                        // Use brightness and color from the light level above TYPE1 level
                        else if (stored.type == SectorLevelType.Light)
                        {
                            l.brightnessbelow = stored.brightnessbelow;
                            l.colorbelow      = stored.colorbelow;
                        }
                        // Otherwise light values from the real ceiling are used
                    }
                    else if (l.lighttype == LightLevelType.UNKNOWN)
                    {
                        // Use stored light level when previous one has "disablelighting" flag
                        // or is the lower boundary of an extrafloor with "restrictlighting" flag
                        SectorLevel src = (pl.disablelighting || (pl.restrictlighting && pl.type == SectorLevelType.Ceiling) ? stored : pl);

                        // Don't change real ceiling light when previous level has "disablelighting" flag
                        // Don't change anything when light properties were reset before hitting floor (otherwise floor UDMF brightness will be lost)
                        if ((src == ceilingbase && l == ceiling) ||
                            (src == ceiling && l == floor && src.LightPropertiesMatch(ceilingbase)))
                        {
                            continue;
                        }

                        // Transfer color and brightness if previous level has them
                        if (src.colorbelow.a > 0 && src.brightnessbelow != -1)
                        {
                            // Only surface brightness is retained when a glowing flat is used as extrafloor texture
                            if (!l.affectedbyglow)
                            {
                                l.color = GetLevelColor(src, l);
                            }

                            // Transfer brightnessbelow and colorbelow if current level is not extrafloor top
                            if (!(l.extrafloor && l.type == SectorLevelType.Floor))
                            {
                                l.brightnessbelow = src.brightnessbelow;
                                l.colorbelow      = src.colorbelow;
                            }
                        }

                        // Store bottom extrafloor level if it doesn't have "restrictlighting" or "restrictlighting" flags set
                        if (l.extrafloor && l.type == SectorLevelType.Ceiling && !l.restrictlighting && !l.disablelighting)
                        {
                            stored = l;
                        }
                    }

                    // Reset lighting?
                    if (l.resetlighting)
                    {
                        stored = ceilingbase;
                    }
                }
            }

            //mxd. Apply ceiling glow effect?
            if (CeilingGlow != null && CeilingGlow.Fullbright)
            {
                ceiling.color = PixelColor.INT_WHITE;
            }

            //mxd. Apply floor glow effect?
            if (FloorGlow != null)
            {
                // Update floor color
                if (FloorGlow.Fullbright)
                {
                    floor.color = PixelColor.INT_WHITE;
                }

                // Update brightness
                floor.brightnessbelow = (FloorGlow.Fullbright ? 255 : Math.Max(128, floor.brightnessbelow));

                if (floor.colorbelow.ToInt() == 0)
                {
                    byte bb = (byte)floor.brightnessbelow;
                    floor.colorbelow = new PixelColor(255, bb, bb, bb);
                }
            }

            //mxd
            floor.affectedbyglow   = (FloorGlow != null);
            ceiling.affectedbyglow = (CeilingGlow != null);

            floorchanged   = false;
            ceilingchanged = false;
            updated        = true;
            isupdating     = false;
        }
Beispiel #20
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);
 }
Beispiel #21
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);

            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
            if (linedef.Args[1] != (int)FloorTypes.VavoomStyle)
            {
                //mxd. check for Swimmable/RenderInside/RenderAdditive flags
                renderadditive = (linedef.Args[2] & (int)Flags.RenderAdditive) == (int)Flags.RenderAdditive;
                renderinside   = ((((linedef.Args[1] & (int)FloorTypes.Swimmable) == (int)FloorTypes.Swimmable) && (linedef.Args[1] & (int)FloorTypes.NonSolid) != (int)FloorTypes.NonSolid)) ||
                                 ((linedef.Args[1] & (int)FloorTypes.RenderInside) == (int)FloorTypes.RenderInside);
                ignorebottomheight = ((linedef.Args[2] & (int)Flags.IgnoreBottomHeight) == (int)Flags.IgnoreBottomHeight);

                vavoomtype = false;
                alpha      = General.Clamp(linedef.Args[3], 0, 255);
                sd.Ceiling.CopyProperties(floor);
                sd.Floor.CopyProperties(ceiling);
                floor.type    = SectorLevelType.Floor;
                floor.plane   = sd.Ceiling.plane.GetInverted();
                ceiling.type  = SectorLevelType.Ceiling;
                ceiling.plane = (ignorebottomheight ? sd.Ceiling.plane : sd.Floor.plane.GetInverted());                 //mxd. Use upper plane when "ignorebottomheight" flag is set

                //mxd
                clipsides = (!renderinside && !renderadditive && alpha > 254 && !ignorebottomheight);

                // A 3D floor's color is always that of the sector it is placed in
                // (unless it's affected by glow) - mxd
                if (sd.CeilingGlow == null || !sd.CeilingGlow.Fullbright)
                {
                    floor.color = 0;
                }
            }
            else
            {
                vavoomtype     = true;
                renderadditive = false;           //mxd
                clipsides      = true;            //mxd
                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
                // (unless it's affected by glow) - mxd
                if (sd.FloorGlow == null || !sd.FloorGlow.Fullbright)
                {
                    ceiling.color = 0;
                }
            }

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

            //mxd
            floor.extrafloor   = true;
            ceiling.extrafloor = true;
            floor.splitsides   = !clipsides;
            ceiling.splitsides = (!clipsides && !ignorebottomheight);             // if "ignorebottomheight" flag is set, both ceiling and floor will be at the same level and sidedef clipping with floor level will fail resulting in incorrect light props transfer in some cases

            //mxd. Check slopes, cause GZDoom can't handle sloped translucent 3d floors...
            sloped3dfloor = ((alpha < 255 || renderadditive) &&
                             (Angle2D.RadToDeg(ceiling.plane.Normal.GetAngleZ()) != 270 ||
                              Angle2D.RadToDeg(floor.plane.Normal.GetAngleZ()) != 90));

            // Do not adjust light? (works only for non-vavoom types)
            if (!vavoomtype)
            {
                bool disablelighting  = ((linedef.Args[2] & (int)Flags.DisableLighting) == (int)Flags.DisableLighting);             //mxd
                bool restrictlighting = ((linedef.Args[2] & (int)Flags.RestrictLighting) == (int)Flags.RestrictLighting);           //mxd
                floor.resetlighting = ((linedef.Args[2] & (int)Flags.ResetLighting) == (int)Flags.ResetLighting);                   //mxd

                if (disablelighting || restrictlighting)
                {
                    floor.restrictlighting = restrictlighting; //mxd
                    floor.disablelighting  = disablelighting;  //mxd

                    if (disablelighting)                       //mxd
                    {
                        floor.color           = 0;
                        floor.brightnessbelow = -1;
                        floor.colorbelow      = PixelColor.FromInt(0);
                    }

                    ceiling.disablelighting  = disablelighting;                    //mxd
                    ceiling.restrictlighting = restrictlighting;                   //mxd

                    ceiling.color           = 0;
                    ceiling.brightnessbelow = -1;
                    ceiling.colorbelow      = PixelColor.FromInt(0);
                }
            }
        }
Beispiel #22
0
        //mxd
        public bool Setup(SectorLevel level, Effect3DFloor extrafloor, bool innerside)
        {
            Sector   s = level.sector;
            Vector2D texscale;

            this.innerside = innerside;

            base.Setup(level, extrafloor);

            // Fetch ZDoom fields
            float    rotate = Angle2D.DegToRad(s.Fields.GetValue("rotationfloor", 0.0f));
            Vector2D offset = new Vector2D(s.Fields.GetValue("xpanningfloor", 0.0f),
                                           s.Fields.GetValue("ypanningfloor", 0.0f));
            Vector2D scale = new Vector2D(s.Fields.GetValue("xscalefloor", 1.0f),
                                          s.Fields.GetValue("yscalefloor", 1.0f));

            //Load floor texture
            if (s.LongFloorTexture != MapSet.EmptyLongName)
            {
                base.Texture = General.Map.Data.GetFlatImage(s.LongFloorTexture);
                if (base.Texture == null || base.Texture is UnknownImage)
                {
                    base.Texture         = General.Map.Data.UnknownTexture3D;
                    setuponloadedtexture = s.LongFloorTexture;
                }
                else if (!base.Texture.IsImageLoaded)
                {
                    setuponloadedtexture = s.LongFloorTexture;
                }
            }
            else
            {
                // Use missing texture
                base.Texture         = General.Map.Data.MissingTexture3D;
                setuponloadedtexture = 0;
            }

            // 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);
            }

            // Determine brightness
            int color = PixelColor.FromInt(level.color).WithAlpha((byte)General.Clamp(level.alpha, 0, 255)).ToInt();

            //mxd. Top extrafloor level should calculate fogdensity
            //from the brightness of the level above it
            int targetbrightness;

            if (extrafloor != null && extrafloor.VavoomType && !level.disablelighting)
            {
                targetbrightness = 0;
                SectorData sd = mode.GetSectorData(this.Sector.Sector);
                for (int i = 0; i < sd.LightLevels.Count - 1; i++)
                {
                    if (sd.LightLevels[i] == level)
                    {
                        targetbrightness = sd.LightLevels[i + 1].brightnessbelow;
                        break;
                    }
                }
            }
            else
            {
                targetbrightness = level.brightnessbelow;
            }

            //mxd. Determine fog density
            fogfactor = CalculateFogFactor(targetbrightness);

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

            WorldVertex[] verts = new WorldVertex[triverts.Count];
            for (int i = 0; i < triverts.Count; i++)
            {
                // Color shading
                verts[i].c = color;                 //mxd

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

                // 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 && !innerside)
            {
                SwapTriangleVertices(verts);
            }

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

            //mxd. Update sky render flag
            UpdateSkyRenderFlag();

            // Apply vertices
            base.SetVertices(verts);
            return(verts.Length > 0);
        }
Beispiel #23
0
        //mxd
        public bool Setup(SectorLevel level, Effect3DFloor extrafloor, bool innerside)
        {
            Sector   s = level.sector;
            Vector2D texscale;

            this.innerside = innerside;             //mxd

            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 ceiling texture
            if (s.LongCeilTexture != MapSet.EmptyLongName)
            {
                base.Texture = General.Map.Data.GetFlatImage(s.LongCeilTexture);
                if (base.Texture == null || base.Texture is UnknownImage)
                {
                    base.Texture         = General.Map.Data.UnknownTexture3D;
                    setuponloadedtexture = s.LongCeilTexture;
                }
                else if (!base.Texture.IsImageLoaded)
                {
                    setuponloadedtexture = s.LongCeilTexture;
                }
            }
            else
            {
                // Use missing texture
                base.Texture         = General.Map.Data.MissingTexture3D;
                setuponloadedtexture = 0;
            }

            // 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);
            }

            // Determine brightness
            byte alpha = (byte)General.Clamp(level.alpha, 0, 255);
            int  color = PixelColor.FromInt(level.color).WithAlpha(alpha).ToInt();
            int  targetbrightness;

            if (extrafloor != null && !extrafloor.VavoomType && !level.disablelighting)
            {
                //mxd. Top extrafloor level should calculate fogdensity from the brightness of the level above it
                if (!innerside)
                {
                    targetbrightness = 0;
                    SectorData sd = mode.GetSectorData(this.Sector.Sector);
                    for (int i = 0; i < sd.LightLevels.Count - 1; i++)
                    {
                        if (sd.LightLevels[i] == level)
                        {
                            targetbrightness = sd.LightLevels[i + 1].brightnessbelow;
                            break;
                        }
                    }
                }
                //mxd. Inner extrafloor ceilings must be colored using control sector's color and brightness
                else
                {
                    targetbrightness = level.brightnessbelow;
                    SectorData sd = mode.GetSectorData(this.Sector.Sector);
                    for (int i = 0; i < sd.LightLevels.Count; i++)
                    {
                        if (sd.LightLevels[i] == level)
                        {
                            if (i > 0)
                            {
                                color = PixelColor.FromInt(sd.LightLevels[i - 1].color).WithAlpha(alpha).ToInt();
                            }
                            break;
                        }
                    }
                }
            }
            else
            {
                targetbrightness = level.brightnessbelow;
            }

            //mxd. Determine fog density
            fogfactor = CalculateFogFactor(targetbrightness);

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

            WorldVertex[] verts = new WorldVertex[triverts.Count];
            for (int i = 0; i < triverts.Count; i++)
            {
                // Color shading
                verts[i].c = color;                 //mxd

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

                // 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 || innerside)
            {
                SwapTriangleVertices(verts);
            }

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

            //mxd. Update sky render flag
            bool isrenderedassky = renderassky;

            renderassky = (level.sector.CeilTexture == General.Map.Config.SkyFlatName);
            if (isrenderedassky != renderassky && Sector.Sides != null)
            {
                // Upper sidedef geometry may need updating...
                foreach (Sidedef side in level.sector.Sidedefs)
                {
                    VisualSidedefParts parts = Sector.GetSidedefParts(side);

                    // Upper side can exist in either our, or the neightbouring sector, right?
                    if (parts.upper != null && parts.upper.Triangles > 0)
                    {
                        parts.upper.UpdateSkyRenderFlag();
                    }
                    else if (side.Other != null && side.Other.Sector != null && side.Other.Sector.CeilTexture == General.Map.Config.SkyFlatName)
                    {
                        // Update upper side of the neightbouring sector
                        BaseVisualSector other = (BaseVisualSector)mode.GetVisualSector(side.Other.Sector);
                        if (other != null && other.Sides != null)
                        {
                            parts = other.GetSidedefParts(side.Other);
                            if (parts.upper != null && parts.upper.Triangles > 0)
                            {
                                parts.upper.UpdateSkyRenderFlag();
                            }
                        }
                    }
                }
            }

            // Apply vertices
            base.SetVertices(verts);
            return(verts.Length > 0);
        }