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