Skip to content

Commit e9052f1

Browse files
committed
Add solid factories for pyramid, tetrahedron, UV sphere, wedge
1 parent 183c776 commit e9052f1

9 files changed

+260
-21
lines changed

Sledge.Formats.Map/Factories/Solids/ConeSolidFactory.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using System;
22
using System.Collections.Generic;
33
using System.ComponentModel;
4-
using System.Linq;
54
using System.Numerics;
65
using Sledge.Formats.Geometric;
76
using Sledge.Formats.Map.Objects;

Sledge.Formats.Map/Factories/Solids/ISolidFactory.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
using System.ComponentModel;
2-
using Sledge.Formats.Map.Objects;
1+
using Sledge.Formats.Map.Objects;
32

43
namespace Sledge.Formats.Map.Factories.Solids
54
{

Sledge.Formats.Map/Factories/Solids/PipeSolidFactory.cs

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using System;
22
using System.Collections.Generic;
33
using System.ComponentModel;
4-
using System.Drawing;
54
using System.Numerics;
65
using Sledge.Formats.Geometric;
76
using Sledge.Formats.Map.Objects;
@@ -22,22 +21,6 @@ public class PipeSolidFactory : SolidFactoryBase
2221
[MapObjectFactoryPropertyData(MinValue = 0.01, DecimalPrecision = 2)]
2322
public int WallWidth { get; set; }
2423

25-
private static Solid MakeSolid(IEnumerable<(string textureName, Vector3[] points)> faces, Color col)
26-
{
27-
var solid = new Solid { Color = col };
28-
foreach (var (texture, arr) in faces)
29-
{
30-
var face = new Face
31-
{
32-
Plane = Plane.CreateFromVertices(arr[0], arr[1], arr[2]),
33-
TextureName = texture
34-
};
35-
face.Vertices.AddRange(arr);
36-
solid.Faces.Add(face);
37-
}
38-
return solid;
39-
}
40-
4124
public override IEnumerable<MapObject> Create(Box box)
4225
{
4326
var numSides = NumberOfSides;
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using System.Collections.Generic;
2+
using System.Numerics;
3+
using Sledge.Formats.Geometric;
4+
using Sledge.Formats.Map.Objects;
5+
6+
namespace Sledge.Formats.Map.Factories.Solids
7+
{
8+
public class PyramidSolidFactory : SolidFactoryBase
9+
{
10+
public override string Name => "Pyramid";
11+
12+
public override IEnumerable<MapObject> Create(Box box)
13+
{
14+
var solid = new Solid
15+
{
16+
Color = ColorUtils.GetRandomBrushColour()
17+
};
18+
19+
// The lower Z plane will be base
20+
var c1 = new Vector3(box.Start.X, box.Start.Y, box.Start.Z).Round(RoundDecimals);
21+
var c2 = new Vector3(box.End.X, box.Start.Y, box.Start.Z).Round(RoundDecimals);
22+
var c3 = new Vector3(box.End.X, box.End.Y, box.Start.Z).Round(RoundDecimals);
23+
var c4 = new Vector3(box.Start.X, box.End.Y, box.Start.Z).Round(RoundDecimals);
24+
var c5 = new Vector3(box.Center.X, box.Center.Y, box.End.Z).Round(RoundDecimals);
25+
var faces = new[]
26+
{
27+
new[] { c4, c3, c2, c1 },
28+
new[] { c5, c1, c2 },
29+
new[] { c5, c2, c3 },
30+
new[] { c5, c3, c4 },
31+
new[] { c5, c4, c1 }
32+
};
33+
foreach (var arr in faces)
34+
{
35+
var face = new Face
36+
{
37+
Plane = Plane.CreateFromVertices(arr[0], arr[1], arr[2]),
38+
TextureName = VisibleTextureName
39+
};
40+
face.Vertices.AddRange(arr);
41+
solid.Faces.Add(face);
42+
}
43+
yield return solid;
44+
}
45+
}
46+
}

Sledge.Formats.Map/Factories/Solids/SolidFactoryBase.cs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
using System.ComponentModel;
1+
using System.Collections.Generic;
2+
using System.ComponentModel;
3+
using System.Drawing;
4+
using System.Numerics;
5+
using Sledge.Formats.Map.Objects;
26

37
namespace Sledge.Formats.Map.Factories.Solids
48
{
@@ -18,5 +22,21 @@ public abstract class SolidFactoryBase : MapObjectFactoryBase, ISolidFactory
1822
[DisplayName("Round decimals")]
1923
[Description("The number of decimals to round vertex positions to")]
2024
public int RoundDecimals { get; set; }
25+
26+
protected static Solid MakeSolid(IEnumerable<(string textureName, Vector3[] points)> faces, Color col)
27+
{
28+
var solid = new Solid { Color = col };
29+
foreach (var (texture, arr) in faces)
30+
{
31+
var face = new Face
32+
{
33+
Plane = Plane.CreateFromVertices(arr[0], arr[1], arr[2]),
34+
TextureName = texture
35+
};
36+
face.Vertices.AddRange(arr);
37+
solid.Faces.Add(face);
38+
}
39+
return solid;
40+
}
2141
}
2242
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
using System.Collections.Generic;
2+
using System.ComponentModel;
3+
using System.Numerics;
4+
using Sledge.Formats.Geometric;
5+
using Sledge.Formats.Map.Objects;
6+
7+
namespace Sledge.Formats.Map.Factories.Solids
8+
{
9+
public class TetrahedronSolidFactory : SolidFactoryBase
10+
{
11+
public override string Name => "Tetrahedron";
12+
13+
[DisplayName("Top vertex at centroid")]
14+
[Description("Put the top vertex at the centroid of the base triangle instead of at the center of the bounding box")]
15+
public bool TopVertexAtCentroid { get; set; }
16+
17+
public override IEnumerable<MapObject> Create(Box box)
18+
{
19+
var useCentroid = TopVertexAtCentroid;
20+
21+
// The lower Z plane will be the triangle, with the lower Y value getting the two corners
22+
var c1 = new Vector3(box.Start.X, box.Start.Y, box.Start.Z).Round(RoundDecimals);
23+
var c2 = new Vector3(box.End.X, box.Start.Y, box.Start.Z).Round(RoundDecimals);
24+
var c3 = new Vector3(box.Center.X, box.End.Y, box.Start.Z).Round(RoundDecimals);
25+
var centroid = new Vector3((c1.X + c2.X + c3.X) / 3, (c1.Y + c2.Y + c3.Y) / 3, box.End.Z);
26+
var c4 = (useCentroid ? centroid : new Vector3(box.Center.X, box.Center.Y, box.End.Z)).Round(RoundDecimals);
27+
28+
var faces = new[] {
29+
new[] { c3, c2, c1 },
30+
new[] { c3, c1, c4 },
31+
new[] { c2, c3, c4 },
32+
new[] { c1, c2, c4 }
33+
};
34+
35+
var solid = new Solid
36+
{
37+
Color = ColorUtils.GetRandomBrushColour()
38+
};
39+
40+
foreach (var arr in faces)
41+
{
42+
var face = new Face
43+
{
44+
Plane = Plane.CreateFromVertices(arr[0], arr[1], arr[2]),
45+
TextureName = VisibleTextureName
46+
};
47+
face.Vertices.AddRange(arr);
48+
solid.Faces.Add(face);
49+
}
50+
yield return solid;
51+
}
52+
}
53+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.ComponentModel;
4+
using System.Numerics;
5+
using Sledge.Formats.Geometric;
6+
using Sledge.Formats.Map.Objects;
7+
8+
namespace Sledge.Formats.Map.Factories.Solids
9+
{
10+
public class UVSphereSolidFactory : SolidFactoryBase
11+
{
12+
public override string Name => "UV Sphere";
13+
14+
[DisplayName("Number of segments (vertical)")]
15+
[Description("The number of segments the sphere will have vertically")]
16+
[MapObjectFactoryPropertyData(MinValue = 3)]
17+
public int NumberOfSegmentsVertical { get; set; }
18+
19+
[DisplayName("Number of segments (horizontal)")]
20+
[Description("The number of segments the sphere will have horizontally")]
21+
[MapObjectFactoryPropertyData(MinValue = 3)]
22+
public int NumberOfSegmentsHorizontal { get; set; }
23+
24+
public override IEnumerable<MapObject> Create(Box box)
25+
{
26+
var numSidesV = NumberOfSegmentsVertical;
27+
if (numSidesV < 3) throw new ArgumentException("NumberOfSegmentsVertical must be >= 3", nameof(NumberOfSegmentsVertical));
28+
29+
var numSidesH = NumberOfSegmentsHorizontal;
30+
if (numSidesH < 3) throw new ArgumentException("NumberOfSegmentsHorizontal must be >= 3", nameof(NumberOfSegmentsHorizontal));
31+
32+
var roundDecimals = Math.Max(2, RoundDecimals); // don't support rounding < 2 because it would result in invalid faces too often
33+
34+
var width = box.Width;
35+
var length = box.Length;
36+
var height = box.Height;
37+
var major = width / 2;
38+
var minor = length / 2;
39+
var heightRadius = height / 2;
40+
41+
var angleV = (float)Math.PI / numSidesV;
42+
var angleH = (float)(Math.PI * 2) / numSidesH;
43+
44+
var faces = new List<(string textureName, Vector3[] points)>();
45+
var bottom = new Vector3(box.Center.X, box.Center.Y, box.Start.Z).Round(roundDecimals);
46+
var top = new Vector3(box.Center.X, box.Center.Y, box.End.Z).Round(roundDecimals);
47+
48+
for (var i = 0; i < numSidesV; i++)
49+
{
50+
// Top -> bottom
51+
var zAngleStart = angleV * i;
52+
var zAngleEnd = angleV * (i + 1);
53+
var zStart = heightRadius * (float)Math.Cos(zAngleStart);
54+
var zEnd = heightRadius * (float)Math.Cos(zAngleEnd);
55+
var zMultStart = (float)Math.Sin(zAngleStart);
56+
var zMultEnd = (float)Math.Sin(zAngleEnd);
57+
for (var j = 0; j < numSidesH; j++)
58+
{
59+
// Go around the circle in X/Y
60+
var xyAngleStart = angleH * j;
61+
var xyAngleEnd = angleH * ((j + 1) % numSidesH);
62+
var xyStartX = major * (float)Math.Cos(xyAngleStart);
63+
var xyStartY = minor * (float)Math.Sin(xyAngleStart);
64+
var xyEndX = major * (float)Math.Cos(xyAngleEnd);
65+
var xyEndY = minor * (float)Math.Sin(xyAngleEnd);
66+
var one = (new Vector3(xyStartX * zMultStart, xyStartY * zMultStart, zStart) + box.Center).Round(roundDecimals);
67+
var two = (new Vector3(xyEndX * zMultStart, xyEndY * zMultStart, zStart) + box.Center).Round(roundDecimals);
68+
var three = (new Vector3(xyEndX * zMultEnd, xyEndY * zMultEnd, zEnd) + box.Center).Round(roundDecimals);
69+
var four = (new Vector3(xyStartX * zMultEnd, xyStartY * zMultEnd, zEnd) + box.Center).Round(roundDecimals);
70+
if (i == 0)
71+
{
72+
// Top faces are triangles
73+
faces.Add((VisibleTextureName, new[] { four, three, top }));
74+
}
75+
else if (i == numSidesV - 1)
76+
{
77+
// Bottom faces are also triangles
78+
faces.Add((VisibleTextureName, new[] { two, one, bottom }));
79+
}
80+
else
81+
{
82+
// Inner faces are quads
83+
faces.Add((VisibleTextureName, new[] { four, three, two, one }));
84+
}
85+
}
86+
}
87+
yield return MakeSolid(faces, ColorUtils.GetRandomBrushColour());
88+
}
89+
}
90+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
using System.Collections.Generic;
2+
using System.Numerics;
3+
using Sledge.Formats.Geometric;
4+
using Sledge.Formats.Map.Objects;
5+
6+
namespace Sledge.Formats.Map.Factories.Solids
7+
{
8+
public class WedgeSolidFactory : SolidFactoryBase
9+
{
10+
public override string Name => "Wedge";
11+
12+
public override IEnumerable<MapObject> Create(Box box)
13+
{
14+
var solid = new Solid
15+
{
16+
Color = ColorUtils.GetRandomBrushColour()
17+
};
18+
19+
// The lower Z plane will be base, the x planes will be triangles
20+
var c1 = new Vector3(box.Start.X, box.Start.Y, box.Start.Z).Round(RoundDecimals);
21+
var c2 = new Vector3(box.End.X, box.Start.Y, box.Start.Z).Round(RoundDecimals);
22+
var c3 = new Vector3(box.End.X, box.End.Y, box.Start.Z).Round(RoundDecimals);
23+
var c4 = new Vector3(box.Start.X, box.End.Y, box.Start.Z).Round(RoundDecimals);
24+
var c5 = new Vector3(box.Center.X, box.Start.Y, box.End.Z).Round(RoundDecimals);
25+
var c6 = new Vector3(box.Center.X, box.End.Y, box.End.Z).Round(RoundDecimals);
26+
var faces = new[]
27+
{
28+
new[] { c4, c3, c2, c1 },
29+
new[] { c5, c1, c2 },
30+
new[] { c2, c3, c6, c5 },
31+
new[] { c6, c3, c4 },
32+
new[] { c4, c1, c5, c6 }
33+
};
34+
foreach (var arr in faces)
35+
{
36+
var face = new Face
37+
{
38+
Plane = Plane.CreateFromVertices(arr[0], arr[1], arr[2]),
39+
TextureName = VisibleTextureName
40+
};
41+
face.Vertices.AddRange(arr);
42+
solid.Faces.Add(face);
43+
}
44+
yield return solid;
45+
}
46+
}
47+
}

Sledge.Formats.sln.DotSettings

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
2+
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=UV/@EntryIndexedValue">UV</s:String></wpf:ResourceDictionary>

0 commit comments

Comments
 (0)