Exemple #1
0
        // This sets up the basic floor and ceiling, as they would be in normal Doom circumstances
        private void BasicSetup()
        {
            // Normal (flat) floor and ceiling planes
            floor.plane   = new Plane(new Vector3D(0, 0, 1), -sector.FloorHeight);
            ceiling.plane = new Plane(new Vector3D(0, 0, -1), sector.CeilHeight);

            // Fetch ZDoom fields
            int  color  = sector.Fields.GetValue("lightcolor", -1);
            int  flight = sector.Fields.GetValue("lightfloor", 0);
            bool fabs   = sector.Fields.GetValue("lightfloorabsolute", false);
            int  clight = sector.Fields.GetValue("lightceiling", 0);
            bool cabs   = sector.Fields.GetValue("lightceilingabsolute", false);

            // Determine colors & light levels
            PixelColor lightcolor = PixelColor.FromInt(color);

            if (!fabs)
            {
                flight = sector.Brightness + flight;
            }
            if (!cabs)
            {
                clight = sector.Brightness + clight;
            }
            PixelColor floorbrightness   = PixelColor.FromInt(mode.CalculateBrightness(flight));
            PixelColor ceilingbrightness = PixelColor.FromInt(mode.CalculateBrightness(clight));
            PixelColor floorcolor        = PixelColor.Modulate(lightcolor, floorbrightness);
            PixelColor ceilingcolor      = PixelColor.Modulate(lightcolor, ceilingbrightness);

            floor.color             = floorcolor.WithAlpha(255).ToInt();
            floor.brightnessbelow   = sector.Brightness;
            floor.colorbelow        = lightcolor.WithAlpha(255);
            ceiling.color           = ceilingcolor.WithAlpha(255).ToInt();
            ceiling.brightnessbelow = sector.Brightness;
            ceiling.colorbelow      = lightcolor.WithAlpha(255);
        }
        // This creates vertices from a wall polygon and applies lighting
        protected List <WorldVertex> CreatePolygonVertices(List <WallPolygon> poly, TexturePlane tp, SectorData sd, int lightvalue, bool lightabsolute)
        {
            List <WallPolygon> polygons = new List <WallPolygon>(poly);
            List <WorldVertex> verts    = new List <WorldVertex>();

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

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

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

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

            return(verts);
        }
        // This 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);
        }