// This builds the geometry. Returns false when no geometry created. public override bool Setup() { //mxd. Middle part exists only when either masked or maskedsolid flag is set bool masked = this.Sidedef.Masked; // wal->cstat & 16 bool maskedsolid = this.Sidedef.MaskedSolid; // wal->cstat & 32 if (masked || maskedsolid) { Vector2D vl, vr; // Left and right vertices for this sidedef if (Sidedef.IsFront) { vl = new Vector2D(Sidedef.Line.Start.Position); vr = new Vector2D(Sidedef.Line.End.Position); } else { vl = new Vector2D(Sidedef.Line.End.Position); vr = new Vector2D(Sidedef.Line.Start.Position); } // Keep top and bottom planes for intersection testing Sector s = Sidedef.Sector; Sector os = Sidedef.Other.Sector; top = ((s.CeilingPlane.GetZ(vl) < os.CeilingPlane.GetZ(vl) && s.CeilingPlane.GetZ(vr) < os.CeilingPlane.GetZ(vr)) ? s.CeilingPlane : os.CeilingPlane); bottom = ((os.FloorPlane.GetZ(vl) > s.FloorPlane.GetZ(vl) && os.FloorPlane.GetZ(vr) > s.FloorPlane.GetZ(vr)) ? os.FloorPlane : s.FloorPlane); // Get ceiling and floor heights float cl = top.GetZ(vl); float cr = top.GetZ(vr); float fl = bottom.GetZ(vl); float fr = bottom.GetZ(vr); // Anything to see? if (cl > fl || cr > fr) { // Mostly the same as upper wall part if (masked && maskedsolid) { // Transparency and brightness int brightness; if (Sidedef.SemiTransparent) { brightness = MapElement.CalculateBrightness(Sidedef.Shade, (byte)(Sidedef.Transparent ? 85 : 170)); this.RenderPass = RenderPass.Alpha; } else { brightness = MapElement.CalculateBrightness(Sidedef.Shade); this.RenderPass = RenderPass.Mask; } // Texture given? Texture = General.Map.Data.GetImageData(Sidedef.MaskedTileIndex); if (Texture is UnknownImage) { // Use missing texture //Texture = General.Map.Data.MissingTexture3D; setuponloadedimage = -1; } else if (!Texture.IsImageLoaded) { setuponloadedimage = Sidedef.MaskedTileIndex; } // Create initial polygon, which is just a quad between floor and ceiling var poly = new List <WorldVertex> { new WorldVertex(vl.x, vl.y, fl, brightness, 0, 0), new WorldVertex(vl.x, vl.y, cl, brightness, 0, 0), new WorldVertex(vr.x, vr.y, cr, brightness, 0, 0), new WorldVertex(vr.x, vr.y, fr, brightness, 0, 0) }; //mxd. Set UV coords the Build way... int xref = (!Sidedef.ImageFlipX ? 1 : 0); int xrefinv = 1 - xref; int yref = (Sidedef.AlignImageToBottom ? Math.Min(Sidedef.Sector.FloorHeight, Sidedef.Other.Sector.FloorHeight) : Math.Max(Sidedef.Sector.CeilingHeight, Sidedef.Other.Sector.CeilingHeight)); float ypancoef = CalculateOffsetV(Sidedef.OffsetY, Texture, false); float scaledtexrepeaty = ((Texture.Height * 128f) / Sidedef.RepeatY); for (int i = 0; i < poly.Count; i++) { var p = poly[i]; float dist = ((i == 2 || i == 3) ? xref : xrefinv); p.u = ((dist * 8.0f * Sidedef.RepeatX) + Sidedef.OffsetX) / Texture.Width; p.v = ((yref + (-p.z)) / scaledtexrepeaty) - ypancoef; if (Sidedef.ImageFlipY) { p.v *= -1; } poly[i] = p; } // Now we create triangles from the polygon. The polygon is convex and clockwise, so this is a piece of cake. List <WorldVertex> verts = new List <WorldVertex>(3); for (int k = 1; k < (poly.Count - 1); k++) { verts.Add(poly[0]); verts.Add(poly[k]); verts.Add(poly[k + 1]); } // Apply vertices SetVertices(verts); return(true); } // Mostly the same as lower wall part else // masked || maskedsolid { //INFO: used refwall props: picnum, palette, shade, xpanning, ypanning var refwall = (Sidedef.SwapBottomImage ? GetNextWall() : Sidedef); int brightness = MapElement.CalculateBrightness(refwall.Shade); // Texture given? Texture = General.Map.Data.GetImageData(refwall.TileIndex); if (Texture is UnknownImage) { // Use missing texture //Texture = General.Map.Data.MissingTexture3D; setuponloadedimage = -1; } else if (!Texture.IsImageLoaded) { setuponloadedimage = Sidedef.TileIndex; } // Create initial polygon, which is just a quad between floor and ceiling var poly = new List <WorldVertex> { new WorldVertex(vl.x, vl.y, fl, brightness, 0, 0), new WorldVertex(vl.x, vl.y, cl, brightness, 0, 0), new WorldVertex(vr.x, vr.y, cr, brightness, 0, 0), new WorldVertex(vr.x, vr.y, fr, brightness, 0, 0) }; //mxd. Set UV coords the Build way... int xref = (!Sidedef.ImageFlipX ? 1 : 0); int xrefinv = 1 - xref; int yref = (!refwall.AlignImageToBottom ? refwall.Other.Sector.FloorHeight : refwall.Sector.CeilingHeight); float ypancoef = CalculateOffsetV(refwall.OffsetY, Texture, !refwall.AlignImageToBottom); float scaledtexrepeaty = ((Texture.Height * 128f) / Sidedef.RepeatY); // (!(wal->cstat & 2) && (wal->cstat & 256)) || ((wal->cstat & 2) && (wall[nwallnum].cstat & 256)) bool flipy = (!Sidedef.SwapBottomImage && Sidedef.ImageFlipY) || (Sidedef.SwapBottomImage && refwall.ImageFlipY); for (int i = 0; i < poly.Count; i++) { var p = poly[i]; float dist = ((i == 2 || i == 3) ? xref : xrefinv); p.u = ((dist * 8.0f * Sidedef.RepeatX) + refwall.OffsetX) / Texture.Width; p.v = ((yref + (-p.z)) / scaledtexrepeaty) - ypancoef; if (flipy) { p.v *= -1; } poly[i] = p; } // Now we create triangles from the polygon. The polygon is convex and clockwise, so this is a piece of cake. List <WorldVertex> verts = new List <WorldVertex>(3); for (int k = 1; k < (poly.Count - 1); k++) { verts.Add(poly[0]); verts.Add(poly[k]); verts.Add(poly[k + 1]); } // Apply vertices base.SetVertices(verts); return(true); } } } // No geometry for invisible wall top = Sidedef.Sector.CeilingPlane; bottom = Sidedef.Sector.CeilingPlane; // bottom same as top so that it has a height of 0 (otherwise it will still be picked up by object picking) SetVertices(new WorldVertex[0]); return(false); }
// This builds the geometry. Returns false when no geometry created. public override bool Setup() { Vector2D vl, vr; // Left and right vertices for this sidedef if (Sidedef.IsFront) { vl = new Vector2D(Sidedef.Line.Start.Position); vr = new Vector2D(Sidedef.Line.End.Position); } else { vl = new Vector2D(Sidedef.Line.End.Position); vr = new Vector2D(Sidedef.Line.Start.Position); } // Keep top and bottom planes for intersection testing //mxd. Our sector's ceiling can be lower than the other sector's floor! Sector s = Sidedef.Sector; Sector os = Sidedef.Other.Sector; top = ((s.CeilingPlane.GetZ(vl) < os.FloorPlane.GetZ(vl) && s.CeilingPlane.GetZ(vr) < os.FloorPlane.GetZ(vr)) ? s.CeilingPlane : os.FloorPlane); bottom = Sidedef.Sector.FloorPlane; // Get ceiling and floor heights float cl = top.GetZ(vl); float cr = top.GetZ(vr); float fl = bottom.GetZ(vl); float fr = bottom.GetZ(vr); // Anything to see? if (cl > fl || cr > fr) { //INFO: used refwall props: picnum, palette, shade, xpanning, ypanning var refwall = (Sidedef.SwapBottomImage ? GetNextWall() : Sidedef); int brightness = MapElement.CalculateBrightness(refwall.Shade); // Texture given? Texture = General.Map.Data.GetImageData(refwall.TileIndex); if (Texture is UnknownImage) { // Use missing texture //Texture = General.Map.Data.MissingTexture3D; setuponloadedimage = -1; } else if (!Texture.IsImageLoaded) { setuponloadedimage = Sidedef.TileIndex; } // Create initial polygon, which is just a quad between floor and ceiling var poly = new List <WorldVertex> { new WorldVertex(vl.x, vl.y, fl, brightness, 0, 0), new WorldVertex(vl.x, vl.y, cl, brightness, 0, 0), new WorldVertex(vr.x, vr.y, cr, brightness, 0, 0), new WorldVertex(vr.x, vr.y, fr, brightness, 0, 0) }; //mxd. Set UV coords the Build way... int xref = (!Sidedef.ImageFlipX ? 1 : 0); int xrefinv = 1 - xref; int yref = (!refwall.AlignImageToBottom ? Sidedef.Other.Sector.FloorHeight : Sidedef.Sector.CeilingHeight); float ypancoef = CalculateOffsetV(refwall.OffsetY, Texture, !refwall.AlignImageToBottom); float scaledtexrepeaty = ((Texture.Height * 128f) / Sidedef.RepeatY); // (!(wal->cstat & 2) && (wal->cstat & 256)) || ((wal->cstat & 2) && (wall[nwallnum].cstat & 256)) bool flipy = (!Sidedef.SwapBottomImage && Sidedef.ImageFlipY) || (Sidedef.SwapBottomImage && refwall.ImageFlipY); for (int i = 0; i < poly.Count; i++) { var p = poly[i]; float dist = ((i == 2 || i == 3) ? xref : xrefinv); p.u = ((dist * 8.0f * Sidedef.RepeatX) + refwall.OffsetX) / Texture.Width; p.v = ((yref + (-p.z)) / scaledtexrepeaty) - ypancoef; if (flipy) { p.v *= -1; } poly[i] = p; } // Cut off the part above the other floor CropPoly(ref poly, top, false); if (poly.Count > 2) { // Now we create triangles from the polygon. The polygon is convex and clockwise, so this is a piece of cake. List <WorldVertex> verts = new List <WorldVertex>(3); for (int k = 1; k < (poly.Count - 1); k++) { verts.Add(poly[0]); verts.Add(poly[k]); verts.Add(poly[k + 1]); } #if DEBUG //mxd. We should have either 3 or 6 verts, right? if (verts.Count != 3 && verts.Count != 6) { throw new NotImplementedException("Unexpected number of vertices!"); } #endif // Apply vertices base.SetVertices(verts); return(true); } } // No geometry for invisible wall base.SetVertices(new WorldVertex[0]); return(false); }
// This builds the thing geometry. Returns false when nothing was created. public virtual bool Setup() { // Must have a width and height! float radius, height; // Find the sector in which the thing resides Thing.DetermineSector(mode.BlockMap); if (sprite != null) { //mxd. Transparency and brightness int brightness; if (Thing.SemiTransparent) { brightness = MapElement.CalculateBrightness(Thing.Shade, (byte)(Thing.Transparent ? 85 : 170)); this.RenderPass = RenderPass.Alpha; } else { brightness = MapElement.CalculateBrightness(Thing.Shade); this.RenderPass = RenderPass.Mask; } // Check if the texture is loaded sprite.LoadImage(); isloaded = sprite.IsImageLoaded; if (isloaded) { base.Texture = sprite; // Determine sprite size and offsets bool flooraligned = Thing.FlatAligned; bool wallaligned = Thing.WallAligned; bool truecentered = Thing.TrueCentered; float xratio = Thing.RepeatX * ((flooraligned && truecentered) ? 0.2f : 0.25f); float yratio = Thing.RepeatY * 0.25f; int xsize = (int)(sprite.Width * xratio); int ysize = (int)(sprite.Height * yratio); int tilexoff = Thing.OffsetX + sprite.OffsetX; int tileyoff = Thing.OffsetY + sprite.OffsetY; int xoff = (int)(tilexoff * xratio); int yoff = (int)(tileyoff * yratio); if (truecentered && !flooraligned) { yoff -= ysize / 2; // Seems that centeryoff shenanigans in polymer_updatesprite.cpp do exactly the same thing... } bool xflip = Thing.FlipX; bool yflip = Thing.FlipY; // Initially set flipu and flipv. bool flipu = (xflip ^ flooraligned); bool flipv = (yflip && !flooraligned); if (flipu) { xoff = -xoff; } if (yflip && (flooraligned || wallaligned)) { yoff = -yoff; } radius = xsize * 0.5f; height = ysize; // Make vertices WorldVertex[] verts = new WorldVertex[6]; verts[0] = new WorldVertex(-radius + xoff, 0.0f, yoff, brightness, 0.0f, 1.0f); verts[1] = new WorldVertex(-radius + xoff, 0.0f, height + yoff, brightness, 0.0f, 0.0f); verts[2] = new WorldVertex(radius + xoff, 0.0f, height + yoff, brightness, 1.0f, 0.0f); verts[3] = verts[0]; verts[4] = verts[2]; verts[5] = new WorldVertex(radius + xoff, 0.0f, yoff, brightness, 1.0f, 1.0f); // Update UVs if needed if (flipu || flipv) { for (int i = 0; i < 6; i++) { if (flipu) { verts[i].u = (verts[i].u - 1.0f) * -1.0f; } if (flipv) { verts[i].v = (verts[i].v - 1.0f) * -1.0f; } } } SetVertices(verts); } else { base.Texture = General.Map.Data.Hourglass3D; // Determine sprite size radius = Math.Min(Texture.Width / 2f, Texture.Height / 2f); height = Math.Min(Texture.Width, Texture.Height); // Make vertices WorldVertex[] verts = new WorldVertex[6]; verts[0] = new WorldVertex(-radius, 0.0f, 0.0f, brightness, 0.0f, 1.0f); verts[1] = new WorldVertex(-radius, 0.0f, height, brightness, 0.0f, 0.0f); verts[2] = new WorldVertex(+radius, 0.0f, height, brightness, 1.0f, 0.0f); verts[3] = verts[0]; verts[4] = verts[2]; verts[5] = new WorldVertex(+radius, 0.0f, 0.0f, brightness, 1.0f, 1.0f); SetVertices(verts); } } else { // Use some default values... radius = MINIMUM_RADIUS; height = MINIMUM_HEIGHT; SetVertices(new WorldVertex[0]); } // Determine position Vector3D pos = Thing.Position; if (Thing.Sector != null) { pos.z = Thing.Sector.FloorPlane.GetZ(Thing.Position.x, Thing.Position.y); } if (Thing.Position.z > 0) { pos.z += Thing.Position.z; } // Check if above ceiling if ((Thing.Sector != null) && ((pos.z + height) > Thing.Sector.CeilingHeight)) { // Put thing against ceiling pos.z = Thing.Sector.CeilingHeight - height; } // Apply settings SetPosition(pos); SetCageSize(Math.Max(radius, MINIMUM_RADIUS), Math.Max(height, MINIMUM_HEIGHT)); SetCageColor(Thing.Color); // Keep info for object picking cageradius2 = radius * Angle2D.SQRT2; cageradius2 = cageradius2 * cageradius2; pos2d = pos; boxp1 = new Vector3D(pos.x - radius, pos.y - radius, pos.z); boxp2 = new Vector3D(pos.x + radius, pos.y + radius, pos.z + height); // Done changed = false; return(true); }
// This builds the geometry. Returns false when no geometry created. public override bool Setup() { // Left and right vertices for this wall Vector2D vl, vr; if (Sidedef.IsFront) { vl = new Vector2D(Sidedef.Line.Start.Position); vr = new Vector2D(Sidedef.Line.End.Position); } else { vl = new Vector2D(Sidedef.Line.End.Position); vr = new Vector2D(Sidedef.Line.Start.Position); } // Keep top and bottom planes for intersection testing top = Sidedef.Sector.CeilingPlane; bottom = Sidedef.Sector.FloorPlane; // Get ceiling and floor heights float cl = top.GetZ(vl); float cr = top.GetZ(vr); float fl = bottom.GetZ(vl); float fr = bottom.GetZ(vr); // Anything to see? if (cl - fl > 0.01f || cr - fr > 0.01f) { int brightness = MapElement.CalculateBrightness(Sidedef.Shade); // Texture given? Texture = General.Map.Data.GetImageData(Sidedef.TileIndex); if (Texture is UnknownImage) { // Use missing texture //Texture = General.Map.Data.MissingTexture3D; setuponloadedimage = -1; } else if (!Texture.IsImageLoaded) { setuponloadedimage = Sidedef.TileIndex; } WorldVertex[] verts = new WorldVertex[6]; verts[0] = new WorldVertex(vl.x, vl.y, fl, brightness, 0, 0); verts[1] = new WorldVertex(vl.x, vl.y, cl, brightness, 0, 0); verts[2] = new WorldVertex(vr.x, vr.y, cr, brightness, 0, 0); verts[3] = verts[0]; verts[4] = verts[2]; verts[5] = new WorldVertex(vr.x, vr.y, fr, brightness, 0, 0); //mxd. Set UV coords the Build way... int xref = (!Sidedef.ImageFlipX ? 1 : 0); int xrefinv = 1 - xref; int yref = (Sidedef.AlignImageToBottom ? Sidedef.Sector.FloorHeight : Sidedef.Sector.CeilingHeight); float ypancoef = CalculateOffsetV(Sidedef.OffsetY, Texture, !Sidedef.AlignImageToBottom); float scaledtexrepeaty = ((Texture.Height * 128f) / Sidedef.RepeatY); for (int i = 0; i < 6; i++) { float dist = ((i == 2 || i == 4 || i == 5) ? xref : xrefinv); verts[i].u = ((dist * 8.0f * Sidedef.RepeatX) + Sidedef.OffsetX) / Texture.Width; // w->wall.buffer[i].v = (-(float)(yref + (w->wall.buffer[i].y * 16)) / ((tilesiz[curpicnum].y * 2048.0f) / (float)(wal->yrepeat))) + ypancoef; verts[i].v = ((yref + (-verts[i].z)) / scaledtexrepeaty) - ypancoef; if (Sidedef.ImageFlipY) { verts[i].v *= -1; } } // Apply vertices SetVertices(verts); return(true); } // No geometry for invisible wall SetVertices(new WorldVertex[0]); return(false); }