Visual mode: regular walls are now clipped by solid 3d floors (this should eliminate z-fighting).

Fixed, WavefrontExporter: floor and ceiling textures were not exported when using "classic" game configurations (ones with disabled "MixTexturesAndFlats" option). This should also fix incorrect flats on exported model when there are flats and textures with the same name.
Fixed, WavefrontExporter: 3d floors geometry and wall geometry around them was created incorrectly.
Fixed, WavefrontExporter: floor and ceiling textures of non-Vavoom 3d floors were swapped on exported geometry.
This commit is contained in:
MaxED 2014-10-28 09:23:21 +00:00
parent 698f57b2f1
commit 0d90d9b297
8 changed files with 392 additions and 188 deletions

View file

@ -151,15 +151,17 @@ namespace CodeImp.DoomBuilder.VisualModes
protected void SetVertices(ICollection<WorldVertex> verts)
{
// Copy vertices
if (verts != null) { //mxd
if(verts != null) //mxd
{
vertices = new WorldVertex[verts.Count];
verts.CopyTo(vertices, 0);
triangles = vertices.Length / 3;
//mxd
CalculateNormals();
} else {
vertices = new WorldVertex[1];
CalculateNormals(); //mxd
}
else
{
vertices = null;
triangles = 0;
}
@ -167,46 +169,50 @@ namespace CodeImp.DoomBuilder.VisualModes
}
//mxd. Normals calculation algorithm taken from OpenGl wiki
protected void CalculateNormals() {
if (triangles > 0) {
int startIndex;
Vector3 U, V;
protected void CalculateNormals()
{
if (triangles == 0) return;
int startIndex;
Vector3 U, V;
BoundingBoxSizes bbs = new BoundingBoxSizes(vertices[0]);
BoundingBoxSizes bbs = new BoundingBoxSizes(vertices[0]);
for (int i = 0; i < triangles; i++) {
startIndex = i * 3;
WorldVertex p1 = vertices[startIndex];
WorldVertex p2 = vertices[startIndex + 1];
WorldVertex p3 = vertices[startIndex + 2];
for(int i = 0; i < triangles; i++)
{
startIndex = i * 3;
WorldVertex p1 = vertices[startIndex];
WorldVertex p2 = vertices[startIndex + 1];
WorldVertex p3 = vertices[startIndex + 2];
U = new Vector3(p2.x - p1.x, p2.y - p1.y, p2.z - p1.z);
V = new Vector3(p3.x - p1.x, p3.y - p1.y, p3.z - p1.z);
U = new Vector3(p2.x - p1.x, p2.y - p1.y, p2.z - p1.z);
V = new Vector3(p3.x - p1.x, p3.y - p1.y, p3.z - p1.z);
p1.nx = p2.nx = p3.nx = -(U.Y * V.Z - U.Z * V.Y);
p1.ny = p2.ny = p3.ny = -(U.Z * V.X - U.X * V.Z);
p1.nz = p2.nz = p3.nz = -(U.X * V.Y - U.Y * V.X);
p1.nx = p2.nx = p3.nx = -(U.Y * V.Z - U.Z * V.Y);
p1.ny = p2.ny = p3.ny = -(U.Z * V.X - U.X * V.Z);
p1.nz = p2.nz = p3.nz = -(U.X * V.Y - U.Y * V.X);
vertices[startIndex] = p1;
vertices[startIndex + 1] = p2;
vertices[startIndex + 2] = p3;
vertices[startIndex] = p1;
vertices[startIndex + 1] = p2;
vertices[startIndex + 2] = p3;
BoundingBoxTools.UpdateBoundingBoxSizes(ref bbs, p1);
BoundingBoxTools.UpdateBoundingBoxSizes(ref bbs, p2);
BoundingBoxTools.UpdateBoundingBoxSizes(ref bbs, p3);
}
boundingBox = BoundingBoxTools.CalculateBoundingPlane(bbs);
BoundingBoxTools.UpdateBoundingBoxSizes(ref bbs, p1);
BoundingBoxTools.UpdateBoundingBoxSizes(ref bbs, p2);
BoundingBoxTools.UpdateBoundingBoxSizes(ref bbs, p3);
}
boundingBox = BoundingBoxTools.CalculateBoundingPlane(bbs);
}
//mxd. Used to get proper sector from 3d-floors
public virtual Sector GetControlSector() {
public virtual Sector GetControlSector()
{
return sector.Sector;
}
//mxd. Used to get proper linedef from 3d-floors
public virtual Linedef GetControlLinedef() {
public virtual Linedef GetControlLinedef()
{
return sidedef.Line;
}

View file

@ -17,13 +17,14 @@ namespace CodeImp.DoomBuilder.BuilderModes.IO
internal struct WavefrontExportSettings
{
public string Obj;
public string ObjName;
public string ObjPath;
public float Scale;
public bool FixScale;
public bool ExportTextures;
public readonly string ObjName;
public readonly string ObjPath;
public readonly float Scale;
public readonly bool FixScale;
public readonly bool ExportTextures;
public bool Valid;
public string[] Textures;
public string[] Flats;
public WavefrontExportSettings(string name, string path, float scale, bool fixScale, bool exportTextures) {
ObjName = name;
@ -35,6 +36,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.IO
Valid = false;
Obj = string.Empty;
Textures = null;
Flats = null;
}
}
@ -69,8 +71,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.IO
continue;
}
if(!id.IsImageLoaded)
id.LoadImage();
if(!id.IsImageLoaded) id.LoadImage();
Bitmap bmp = id.GetBitmap();
bmp.Save(Path.Combine(settings.ObjPath, s + ".PNG"), ImageFormat.Png);
} else {
@ -78,6 +79,33 @@ namespace CodeImp.DoomBuilder.BuilderModes.IO
}
}
}
if (settings.Flats != null) {
foreach(string s in settings.Flats) {
if(s == DEFAULT) continue;
if(General.Map.Data.GetFlatExists(s)) {
ImageData id = General.Map.Data.GetFlatImage(s);
if(id.Width == 0 || id.Height == 0) {
General.ErrorLogger.Add(ErrorType.Warning, "OBJ Exporter: flat '" + s + "' has invalid size (" + id.Width + "x" + id.Height + ")!");
continue;
}
if(!id.IsImageLoaded) id.LoadImage();
Bitmap bmp = id.GetBitmap();
// Handle duplicate names
string flatname = s;
if(settings.Textures != null && Array.IndexOf(settings.Textures, s) != -1) {
flatname += "_FLAT";
}
bmp.Save(Path.Combine(settings.ObjPath, flatname + ".PNG"), ImageFormat.Png);
} else {
General.ErrorLogger.Add(ErrorType.Warning, "OBJ Exporter: flat '" + s + "' does not exist!");
}
}
}
}
//write obj
@ -90,12 +118,32 @@ namespace CodeImp.DoomBuilder.BuilderModes.IO
mtl.Append("# MTL for " + General.Map.FileTitle + ", map " + General.Map.Options.LevelName + Environment.NewLine);
mtl.Append("# Created by GZDoom Builder " + Application.ProductVersion + Environment.NewLine + Environment.NewLine);
foreach(string s in settings.Textures) {
if(s == DEFAULT) continue;
mtl.Append("newmtl " + s.ToUpperInvariant() + Environment.NewLine);
mtl.Append("Kd 1.0 1.0 1.0" + Environment.NewLine);
if(settings.ExportTextures) mtl.Append("map_Kd " + Path.Combine(settings.ObjPath, s.ToUpperInvariant() + ".PNG") + Environment.NewLine);
mtl.Append(Environment.NewLine);
if (settings.Textures != null) {
foreach (string s in settings.Textures) {
if (s == DEFAULT) continue;
mtl.Append("newmtl " + s.ToUpperInvariant() + Environment.NewLine);
mtl.Append("Kd 1.0 1.0 1.0" + Environment.NewLine);
if (settings.ExportTextures) mtl.Append("map_Kd " + Path.Combine(settings.ObjPath, s.ToUpperInvariant() + ".PNG") + Environment.NewLine);
mtl.Append(Environment.NewLine);
}
}
if(settings.Flats != null) {
foreach (string s in settings.Flats) {
if (s == DEFAULT) continue;
mtl.Append("newmtl " + s.ToUpperInvariant() + Environment.NewLine);
mtl.Append("Kd 1.0 1.0 1.0" + Environment.NewLine);
if (settings.ExportTextures) {
// Handle duplicate names
string flatname = s;
if(settings.Textures != null && Array.IndexOf(settings.Textures, s) != -1) {
flatname += "_FLAT";
}
mtl.Append("map_Kd " + Path.Combine(settings.ObjPath, flatname.ToUpperInvariant() + ".PNG") + Environment.NewLine);
}
mtl.Append(Environment.NewLine);
}
}
//write mtl
@ -131,14 +179,13 @@ namespace CodeImp.DoomBuilder.BuilderModes.IO
}
//sort geometry
Dictionary<string, List<WorldVertex[]>> geometryByTexture = sortGeometry(visualSectors);
List<Dictionary<string, List<WorldVertex[]>>> geometryByTexture = sortGeometry(visualSectors);
//restore vm settings
if(renderingEffectsDisabled)
mode.ToggleGZDoomRenderingEffects();
mode.Dispose();
mode = null;
//create obj
StringBuilder obj = createObjGeometry(geometryByTexture, data);
@ -154,32 +201,39 @@ namespace CodeImp.DoomBuilder.BuilderModes.IO
obj.Insert(0, "# " + General.Map.FileTitle + ", map " + General.Map.Options.LevelName + Environment.NewLine);
data.Obj = obj.ToString();
string[] textures = new string[geometryByTexture.Keys.Count];
geometryByTexture.Keys.CopyTo(textures, 0);
string[] textures = new string[geometryByTexture[0].Keys.Count];
geometryByTexture[0].Keys.CopyTo(textures, 0);
Array.Sort(textures);
data.Textures = textures;
string[] flats = new string[geometryByTexture[1].Keys.Count];
geometryByTexture[1].Keys.CopyTo(flats, 0);
Array.Sort(flats);
data.Flats = flats;
data.Valid = true;
}
private Dictionary<string, List<WorldVertex[]>> sortGeometry(List<BaseVisualSector> visualSectors) {
var geo = new Dictionary<string, List<WorldVertex[]>>(StringComparer.Ordinal);
geo.Add(DEFAULT, new List<WorldVertex[]>());
private List<Dictionary<string, List<WorldVertex[]>>> sortGeometry(List<BaseVisualSector> visualSectors) {
var texturegeo = new Dictionary<string, List<WorldVertex[]>>(StringComparer.Ordinal);
texturegeo.Add(DEFAULT, new List<WorldVertex[]>());
var flatgeo = new Dictionary<string, List<WorldVertex[]>>(StringComparer.Ordinal);
flatgeo.Add(DEFAULT, new List<WorldVertex[]>());
string texture;
foreach(BaseVisualSector vs in visualSectors) {
//floor
if(vs.Floor != null) {
texture = vs.Sector.FloorTexture;
checkTextureName(ref geo, ref texture);
geo[texture].AddRange(optimizeSector(vs.Floor.Vertices, vs.Floor.GeometryType));
checkTextureName(ref flatgeo, ref texture);
flatgeo[texture].AddRange(OptimizeGeometry(vs.Floor.Vertices, vs.Floor.GeometryType, vs.Floor.Sector.Sector.Labels.Count > 1));
}
//ceiling
if(vs.Ceiling != null) {
texture = vs.Sector.CeilTexture;
checkTextureName(ref geo, ref texture);
geo[texture].AddRange(optimizeSector(vs.Ceiling.Vertices, vs.Ceiling.GeometryType));
checkTextureName(ref flatgeo, ref texture);
flatgeo[texture].AddRange(OptimizeGeometry(vs.Ceiling.Vertices, vs.Ceiling.GeometryType, vs.Ceiling.Sector.Sector.Labels.Count > 1));
}
//walls
@ -188,31 +242,31 @@ namespace CodeImp.DoomBuilder.BuilderModes.IO
//upper
if(part.upper != null && part.upper.Vertices != null) {
texture = part.upper.Sidedef.HighTexture;
checkTextureName(ref geo, ref texture);
geo[texture].Add(optimizeWall(part.upper.Vertices));
checkTextureName(ref texturegeo, ref texture);
texturegeo[texture].AddRange(OptimizeGeometry(part.upper.Vertices, part.upper.GeometryType));
}
//middle single
if(part.middlesingle != null && part.middlesingle.Vertices != null) {
texture = part.middlesingle.Sidedef.MiddleTexture;
checkTextureName(ref geo, ref texture);
geo[texture].Add(optimizeWall(part.middlesingle.Vertices));
checkTextureName(ref texturegeo, ref texture);
texturegeo[texture].AddRange(OptimizeGeometry(part.middlesingle.Vertices, part.middlesingle.GeometryType));
}
//middle double
if(part.middledouble != null && part.middledouble.Vertices != null) {
texture = part.middledouble.Sidedef.MiddleTexture;
checkTextureName(ref geo, ref texture);
geo[texture].Add(optimizeWall(part.middledouble.Vertices));
checkTextureName(ref texturegeo, ref texture);
texturegeo[texture].AddRange(OptimizeGeometry(part.middledouble.Vertices, part.middledouble.GeometryType));
}
//middle3d
if(part.middle3d != null && part.middle3d.Count > 0) {
foreach(VisualMiddle3D m3d in part.middle3d) {
if(m3d.Vertices == null) continue;
texture = m3d.Sidedef.MiddleTexture;
checkTextureName(ref geo, ref texture);
geo[texture].Add(optimizeWall(m3d.Vertices));
texture = m3d.GetControlLinedef().Front.MiddleTexture;
checkTextureName(ref texturegeo, ref texture);
texturegeo[texture].AddRange(OptimizeGeometry(m3d.Vertices, m3d.GeometryType));
}
}
@ -221,30 +275,30 @@ namespace CodeImp.DoomBuilder.BuilderModes.IO
//lower
if(part.lower != null && part.lower.Vertices != null) {
texture = part.lower.Sidedef.LowTexture;
checkTextureName(ref geo, ref texture);
geo[texture].Add(optimizeWall(part.lower.Vertices));
checkTextureName(ref texturegeo, ref texture);
texturegeo[texture].AddRange(OptimizeGeometry(part.lower.Vertices, part.lower.GeometryType));
}
}
}
//3d ceilings
foreach(VisualCeiling vc in vs.ExtraCeilings) {
texture = vc.GetControlSector().FloorTexture;
checkTextureName(ref geo, ref texture);
geo[texture].AddRange(optimizeSector(vc.Vertices, vc.GeometryType));
texture = vc.GetControlSector().CeilTexture;
checkTextureName(ref flatgeo, ref texture);
flatgeo[texture].AddRange(OptimizeGeometry(vc.Vertices, (vc.ExtraFloor.VavoomType ? vc.GeometryType : VisualModes.VisualGeometryType.FLOOR)));
}
//3d floors
foreach(VisualFloor vf in vs.ExtraFloors) {
texture = vf.GetControlSector().FloorTexture;
checkTextureName(ref geo, ref texture);
geo[texture].AddRange(optimizeSector(vf.Vertices, vf.GeometryType));
checkTextureName(ref flatgeo, ref texture);
flatgeo[texture].AddRange(OptimizeGeometry(vf.Vertices, (vf.ExtraFloor.VavoomType ? vf.GeometryType : VisualModes.VisualGeometryType.CEILING)));
}
//backsides(?)
}
return geo;
return new List<Dictionary<string, List<WorldVertex[]>>> { texturegeo, flatgeo };
}
private static void checkTextureName(ref Dictionary<string, List<WorldVertex[]>> geo, ref string texture) {
@ -257,24 +311,19 @@ namespace CodeImp.DoomBuilder.BuilderModes.IO
}
//SURFACE OPTIMIZATION
//it's either quad, or triangle
private static WorldVertex[] optimizeWall(WorldVertex[] verts) {
if (verts.Length == 6) {
return new[] { verts[5], verts[2], verts[1], verts[0] };
}
Array.Reverse(verts);
return verts;
private static List<WorldVertex[]> OptimizeGeometry(WorldVertex[] verts, VisualModes.VisualGeometryType geotype)
{
return OptimizeGeometry(verts, geotype, false);
}
private static List<WorldVertex[]> optimizeSector(WorldVertex[] verts, VisualModes.VisualGeometryType visualGeometryType) {
private static List<WorldVertex[]> OptimizeGeometry(WorldVertex[] verts, VisualModes.VisualGeometryType geotype, bool skiprectoptimization) {
List<WorldVertex[]> groups = new List<WorldVertex[]>();
if(verts.Length == 6) { //rectangle surface
if (visualGeometryType == VisualModes.VisualGeometryType.FLOOR) {
verts = new[] { verts[5], verts[2], verts[1], verts[0] };
} else {
if(!skiprectoptimization && verts.Length == 6) { //rectangular surface
if(geotype == VisualModes.VisualGeometryType.CEILING) {
verts = new[] { verts[2], verts[5], verts[1], verts[0] };
} else {
verts = new[] { verts[5], verts[2], verts[1], verts[0] };
}
groups.Add(verts);
} else {
@ -287,7 +336,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.IO
}
//OBJ Creation
private static StringBuilder createObjGeometry(Dictionary<string, List<WorldVertex[]>> geometryByTexture, WavefrontExportSettings data) {
private static StringBuilder createObjGeometry(List<Dictionary<string, List<WorldVertex[]>>> geometryByTexture, WavefrontExportSettings data) {
StringBuilder obj = new StringBuilder();
const string vertexFormatter = "{0} {2} {1}\n";
@ -302,46 +351,56 @@ namespace CodeImp.DoomBuilder.BuilderModes.IO
int uvc = 0;
//optimize geometry
foreach(KeyValuePair<string, List<WorldVertex[]>> group in geometryByTexture) {
Dictionary<WorldVertex, VertexIndices> vertsData = new Dictionary<WorldVertex, VertexIndices>();
foreach(WorldVertex[] verts in group.Value) {
//vertex normals
Vector3D n = new Vector3D(verts[0].nx, verts[0].ny, verts[0].nz).GetNormal();
if(uniqueNormals.ContainsKey(n)) {
ni = uniqueNormals[n];
} else {
uniqueNormals.Add(n, ++nc);
ni = nc;
}
foreach(WorldVertex v in verts){
if(vertsData.ContainsKey(v)) continue;
VertexIndices indices = new VertexIndices();
indices.NormalIndex = ni;
//vertex coords
Vector3D vc = new Vector3D(v.x, v.y, v.z);
if(uniqueVerts.ContainsKey(vc)) {
indices.PositionIndex = uniqueVerts[vc];
foreach(Dictionary<string, List<WorldVertex[]>> dictionary in geometryByTexture) {
foreach(KeyValuePair<string, List<WorldVertex[]>> group in dictionary) {
Dictionary<WorldVertex, VertexIndices> vertsData = new Dictionary<WorldVertex, VertexIndices>();
foreach(WorldVertex[] verts in group.Value) {
//vertex normals
Vector3D n = new Vector3D(verts[0].nx, verts[0].ny, verts[0].nz).GetNormal();
if (uniqueNormals.ContainsKey(n)) {
ni = uniqueNormals[n];
} else {
uniqueVerts.Add(vc, ++pc);
indices.PositionIndex = pc;
uniqueNormals.Add(n, ++nc);
ni = nc;
}
//uv
PointF uv = new PointF(v.u, v.v);
if(uniqueUVs.ContainsKey(uv)) {
indices.UVIndex = uniqueUVs[uv];
}else{
uniqueUVs.Add(uv, ++uvc);
indices.UVIndex = uvc;
}
foreach(WorldVertex v in verts) {
if (vertsData.ContainsKey(v)) continue;
VertexIndices indices = new VertexIndices();
indices.NormalIndex = ni;
vertsData.Add(v, indices);
//vertex coords
Vector3D vc = new Vector3D(v.x, v.y, v.z);
if (uniqueVerts.ContainsKey(vc)) {
indices.PositionIndex = uniqueVerts[vc];
} else {
uniqueVerts.Add(vc, ++pc);
indices.PositionIndex = pc;
}
//uv
PointF uv = new PointF(v.u, v.v);
if (uniqueUVs.ContainsKey(uv)) {
indices.UVIndex = uniqueUVs[uv];
} else {
uniqueUVs.Add(uv, ++uvc);
indices.UVIndex = uvc;
}
vertsData.Add(v, indices);
}
}
if(vertsData.Count > 0) {
if(vertexDataByTexture.ContainsKey(group.Key)) {
foreach(KeyValuePair<WorldVertex, VertexIndices> g in vertsData) {
vertexDataByTexture[group.Key].Add(g.Key, g.Value);
}
} else {
vertexDataByTexture.Add(group.Key, vertsData);
}
}
}
vertexDataByTexture.Add(group.Key, vertsData);
}
//write geometry
@ -366,18 +425,20 @@ namespace CodeImp.DoomBuilder.BuilderModes.IO
obj.Append("mtllib ").Append(data.ObjName + ".mtl").Append("\n");
//write materials and surface indices
foreach(KeyValuePair<string, List<WorldVertex[]>> group in geometryByTexture) {
//material
obj.Append("usemtl ").Append(group.Key).Append("\n");
foreach(WorldVertex[] verts in group.Value) {
//surface indices
obj.Append("f");
foreach(WorldVertex v in verts) {
VertexIndices vi = vertexDataByTexture[group.Key][v];
obj.Append(" " + vi.PositionIndex + "/" + vi.UVIndex + "/" + vi.NormalIndex);
foreach(Dictionary<string, List<WorldVertex[]>> dictionary in geometryByTexture) {
foreach(KeyValuePair<string, List<WorldVertex[]>> group in dictionary) {
//material
obj.Append("usemtl ").Append(group.Key).Append("\n");
foreach(WorldVertex[] verts in group.Value) {
//surface indices
obj.Append("f");
foreach(WorldVertex v in verts) {
VertexIndices vi = vertexDataByTexture[group.Key][v];
obj.Append(" " + vi.PositionIndex + "/" + vi.UVIndex + "/" + vi.NormalIndex);
}
obj.Append("\n");
}
obj.Append("\n");
}
}

View file

@ -178,22 +178,53 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Cut off the part above the other floor
CropPoly(ref poly, osd.Floor.plane, false);
CropPoly(ref poly, osd.Ceiling.plane, true);
if(poly.Count > 2)
// Cut out pieces that overlap 3D floors in this sector
List<WallPolygon> polygons = new List<WallPolygon>(1);
polygons.Add(poly);
foreach(Effect3DFloor ef in sd.ExtraFloors) {
//mxd. Walls should be clipped by solid 3D floors
if(!ef.RenderInside && ef.Alpha == 255) {
int num = polygons.Count;
for(int pi = 0; pi < num; pi++) {
// Split by floor plane of 3D floor
WallPolygon p = polygons[pi];
WallPolygon np = SplitPoly(ref p, ef.Ceiling.plane, true);
if(np.Count > 0) {
// Split part below floor by the ceiling plane of 3D floor
// and keep only the part below the ceiling (front)
SplitPoly(ref np, ef.Floor.plane, true);
if(p.Count == 0) {
polygons[pi] = np;
} else {
polygons[pi] = p;
polygons.Add(np);
}
} else {
polygons[pi] = p;
}
}
}
}
if(polygons.Count > 0)
{
// Keep top and bottom planes for intersection testing
top = osd.Floor.plane;
bottom = sd.Floor.plane;
// Process the polygon and create vertices
List<WorldVertex> verts = CreatePolygonVertices(poly, tp, sd, lightvalue, lightabsolute);
if(verts.Count > 0)
List<WorldVertex> verts = CreatePolygonVertices(polygons, tp, sd, lightvalue, lightabsolute);
if(verts.Count > 2)
{
base.SetVertices(verts);
return true;
}
}
base.SetVertices(null); //mxd
return false;
}

View file

@ -255,37 +255,41 @@ namespace CodeImp.DoomBuilder.BuilderModes
}
// Process the polygon and create vertices
List<WorldVertex> verts = CreatePolygonVertices(polygons, tp, sd, lightvalue, lightabsolute);
if(verts.Count > 0)
if (polygons.Count > 0)
{
if ((extrafloor.Linedef.Args[2] & (int)Effect3DFloor.Flags.RenderAdditive) != 0)//mxd
this.RenderPass = RenderPass.Additive;
else if (extrafloor.Alpha < 255)
this.RenderPass = RenderPass.Alpha;
else
this.RenderPass = RenderPass.Mask;
if(extrafloor.Alpha < 255)
List<WorldVertex> verts = CreatePolygonVertices(polygons, tp, sd, lightvalue, lightabsolute);
if (verts.Count > 2)
{
// Apply alpha to vertices
byte alpha = (byte)General.Clamp(extrafloor.Alpha, 0, 255);
if(alpha < 255)
if ((extrafloor.Linedef.Args[2] & (int) Effect3DFloor.Flags.RenderAdditive) != 0) //mxd
this.RenderPass = RenderPass.Additive;
else if (extrafloor.Alpha < 255)
this.RenderPass = RenderPass.Alpha;
else
this.RenderPass = RenderPass.Mask;
if (extrafloor.Alpha < 255)
{
for(int i = 0; i < verts.Count; i++)
// Apply alpha to vertices
byte alpha = (byte) General.Clamp(extrafloor.Alpha, 0, 255);
if (alpha < 255)
{
WorldVertex v = verts[i];
PixelColor c = PixelColor.FromInt(v.c);
v.c = c.WithAlpha(alpha).ToInt();
verts[i] = v;
for (int i = 0; i < verts.Count; i++)
{
WorldVertex v = verts[i];
PixelColor c = PixelColor.FromInt(v.c);
v.c = c.WithAlpha(alpha).ToInt();
verts[i] = v;
}
}
}
base.SetVertices(verts);
return true;
}
base.SetVertices(verts);
return true;
}
}
base.SetVertices(null); //mxd
return false;
}

View file

@ -219,34 +219,41 @@ namespace CodeImp.DoomBuilder.BuilderModes {
}
// Process the polygon and create vertices
List<WorldVertex> verts = CreatePolygonVertices(polygons, tp, sd, lightvalue, lightabsolute);
if(verts.Count > 0)
if (polygons.Count > 0)
{
if ((extrafloor.Linedef.Args[2] & (int)Effect3DFloor.Flags.RenderAdditive) != 0)//mxd
this.RenderPass = RenderPass.Additive;
else if (extrafloor.Alpha < 255)
this.RenderPass = RenderPass.Alpha;
else
this.RenderPass = RenderPass.Mask;
List<WorldVertex> verts = CreatePolygonVertices(polygons, tp, sd, lightvalue, lightabsolute);
if (verts.Count > 2)
{
if ((extrafloor.Linedef.Args[2] & (int) Effect3DFloor.Flags.RenderAdditive) != 0) //mxd
this.RenderPass = RenderPass.Additive;
else if (extrafloor.Alpha < 255)
this.RenderPass = RenderPass.Alpha;
else
this.RenderPass = RenderPass.Mask;
if (extrafloor.Alpha < 255) {
// Apply alpha to vertices
byte alpha = (byte)General.Clamp(extrafloor.Alpha, 0, 255);
if (alpha < 255) {
for (int i = 0; i < verts.Count; i++) {
WorldVertex v = verts[i];
PixelColor c = PixelColor.FromInt(v.c);
v.c = c.WithAlpha(alpha).ToInt();
verts[i] = v;
if (extrafloor.Alpha < 255)
{
// Apply alpha to vertices
byte alpha = (byte) General.Clamp(extrafloor.Alpha, 0, 255);
if (alpha < 255)
{
for (int i = 0; i < verts.Count; i++)
{
WorldVertex v = verts[i];
PixelColor c = PixelColor.FromInt(v.c);
v.c = c.WithAlpha(alpha).ToInt();
verts[i] = v;
}
}
}
base.SetVertices(verts);
return true;
}
base.SetVertices(verts);
return true;
}
}
base.SetVertices(null); //mxd
return false;
}

View file

@ -206,14 +206,44 @@ namespace CodeImp.DoomBuilder.BuilderModes
CropPoly(ref poly, bottomclipplane, true);
}
if(poly.Count > 2) {
// Cut out pieces that overlap 3D floors in this sector
List<WallPolygon> polygons = new List<WallPolygon>(1);
polygons.Add(poly);
foreach(Effect3DFloor ef in sd.ExtraFloors) {
//mxd. Walls should be clipped by solid 3D floors
if(!ef.RenderInside && ef.Alpha == 255) {
int num = polygons.Count;
for(int pi = 0; pi < num; pi++) {
// Split by floor plane of 3D floor
WallPolygon p = polygons[pi];
WallPolygon np = SplitPoly(ref p, ef.Ceiling.plane, true);
if(np.Count > 0) {
// Split part below floor by the ceiling plane of 3D floor
// and keep only the part below the ceiling (front)
SplitPoly(ref np, ef.Floor.plane, true);
if(p.Count == 0) {
polygons[pi] = np;
} else {
polygons[pi] = p;
polygons.Add(np);
}
} else {
polygons[pi] = p;
}
}
}
}
if(polygons.Count > 0) {
// Keep top and bottom planes for intersection testing
top = osd.Ceiling.plane;
bottom = osd.Floor.plane;
// Process the polygon and create vertices
List<WorldVertex> verts = CreatePolygonVertices(poly, tp, sd, lightvalue, lightabsolute);
if(verts.Count > 0) {
List<WorldVertex> verts = CreatePolygonVertices(polygons, tp, sd, lightvalue, lightabsolute);
if(verts.Count > 2) {
// Apply alpha to vertices
byte alpha = SetLinedefRenderstyle(true);
if(alpha < 255) {

View file

@ -180,16 +180,50 @@ namespace CodeImp.DoomBuilder.BuilderModes
PixelColor wallbrightness = PixelColor.FromInt(mode.CalculateBrightness(lightlevel, Sidedef));
PixelColor wallcolor = PixelColor.Modulate(sd.Ceiling.colorbelow, wallbrightness);
poly.color = wallcolor.WithAlpha(255).ToInt();
// Process the polygon and create vertices
List<WorldVertex> verts = CreatePolygonVertices(poly, tp, sd, lightvalue, lightabsolute);
if(verts.Count > 0)
// Cut out pieces that overlap 3D floors in this sector
List<WallPolygon> polygons = new List<WallPolygon>(1);
polygons.Add(poly);
foreach(Effect3DFloor ef in sd.ExtraFloors) {
//mxd. Walls should be clipped by solid 3D floors
if(!ef.RenderInside && ef.Alpha == 255) {
int num = polygons.Count;
for(int pi = 0; pi < num; pi++) {
// Split by floor plane of 3D floor
WallPolygon p = polygons[pi];
WallPolygon np = SplitPoly(ref p, ef.Ceiling.plane, true);
if(np.Count > 0) {
// Split part below floor by the ceiling plane of 3D floor
// and keep only the part below the ceiling (front)
SplitPoly(ref np, ef.Floor.plane, true);
if(p.Count == 0) {
polygons[pi] = np;
} else {
polygons[pi] = p;
polygons.Add(np);
}
} else {
polygons[pi] = p;
}
}
}
}
if (polygons.Count > 0)
{
base.SetVertices(verts);
return true;
// Process the polygon and create vertices
List<WorldVertex> verts = CreatePolygonVertices(polygons, tp, sd, lightvalue, lightabsolute);
if (verts.Count > 2)
{
base.SetVertices(verts);
return true;
}
}
}
base.SetVertices(null); //mxd
return false;
}

View file

@ -173,21 +173,52 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Cut off the part below the other ceiling
CropPoly(ref poly, osd.Ceiling.plane, false);
if(poly.Count > 2)
// Cut out pieces that overlap 3D floors in this sector
List<WallPolygon> polygons = new List<WallPolygon>(1);
polygons.Add(poly);
foreach(Effect3DFloor ef in sd.ExtraFloors) {
//mxd. Walls should be clipped by solid 3D floors
if(!ef.RenderInside && ef.Alpha == 255) {
int num = polygons.Count;
for(int pi = 0; pi < num; pi++) {
// Split by floor plane of 3D floor
WallPolygon p = polygons[pi];
WallPolygon np = SplitPoly(ref p, ef.Ceiling.plane, true);
if(np.Count > 0) {
// Split part below floor by the ceiling plane of 3D floor
// and keep only the part below the ceiling (front)
SplitPoly(ref np, ef.Floor.plane, true);
if(p.Count == 0) {
polygons[pi] = np;
} else {
polygons[pi] = p;
polygons.Add(np);
}
} else {
polygons[pi] = p;
}
}
}
}
if(polygons.Count > 0)
{
// Keep top and bottom planes for intersection testing
top = sd.Ceiling.plane;
bottom = osd.Ceiling.plane;
// Process the polygon and create vertices
List<WorldVertex> verts = CreatePolygonVertices(poly, tp, sd, lightvalue, lightabsolute);
if(verts.Count > 0)
List<WorldVertex> verts = CreatePolygonVertices(polygons, tp, sd, lightvalue, lightabsolute);
if(verts.Count > 2)
{
base.SetVertices(verts);
return true;
}
}
base.SetVertices(null); //mxd
return false;
}