Skip to content

Commit 4187db9

Browse files
authored
Merge pull request #12 from CptWesley/patch-support#1
Patch support
2 parents 8b53f7f + 3287315 commit 4187db9

8 files changed

Lines changed: 211 additions & 16 deletions

File tree

README.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,16 @@ Converts (Gtk)Radiant .map files to Wavefront .obj formatted files.
44
### Usage:
55
Drag and drop a .map file onto the .exe
66

7+
#### Program arguments:
8+
- `autoclose` (e.g. `-autoclose=true`)
9+
- `scale` (e.g. `-scale=0.01`)
10+
- `filter` (e.g. `-filter=cod1filter.txt`)
11+
712
### Confirmed working for:
8-
- GtkRadiant 1.6.5 Wolfenstein: Enemy Territory
13+
- GtkRadiant 1.6.5 Wolfenstein: Enemy Territory *(brush+patches)*
14+
- GtkRadiant 1.5.0 Wolfenstein: Enemy Territory *(brush+patches)*
15+
- CoD Radiant *(brush+patches)*
16+
- CoDWaW Radiant *(brush)*
917

1018
(*if there are any .map formats not supported, please notify me*)
1119

src/Brush.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,13 @@ public static Brush CreateFromCode(string[] code)
2424
// Creates the needed clipping planes based on code.
2525
private static ClippingPlane[] CreateClippingPlanes(string[] code)
2626
{
27-
string pattern = @"(\(\s?-?\d+(\.\d+)?\s-?\d+(\.\d+)?\s-?\d+(\.\d+)?\s?\))\s?" // First vertex [1]
28-
+ @"(\(\s?-?\d+(\.\d+)?\s-?\d+(\.\d+)?\s-?\d+(\.\d+)?\s?\))\s?" // Second vertex [5]
29-
+ @"(\(\s?-?\d+(\.\d+)?\s-?\d+(\.\d+)?\s-?\d+(\.\d+)?\s?\))\s" // Third vertex [9]
30-
+ @"(\w+(\/\S*)*)" // Texture [13]
31-
+ @".*"; // Leftovers
27+
string num = @"-?\d+(\.\d+)?";
28+
string vertex = @"(\(\s?" + num + @"\s" + num + @"\s" + num + @"\s?\))";
29+
string pattern = vertex + @"\s?" // First vertex [1]
30+
+ vertex + @"\s?" // Second vertex [5]
31+
+ vertex + @"\s" // Third vertex [9]
32+
+ @"(\w+(\/\S*)*)" // Texture [13]
33+
+ @".*"; // Leftovers
3234
Regex regex = new Regex(pattern, RegexOptions.IgnoreCase);
3335

3436
List<ClippingPlane> planes = new List<ClippingPlane>();

src/Face.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ public class Face
77
private Vertex[] _vertices;
88
public string Texture { get; private set; }
99

10+
public Vertex this[int index]
11+
{
12+
get => _vertices[index];
13+
set => _vertices[index] = value;
14+
}
15+
1016
// Empty contructor that creates an empty face.
1117
public Face()
1218
{

src/ObjObject.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,15 @@ public static ObjObject CreateFromBrush(string name, Brush brush)
129129
return new ObjObject(name, vertices, faces);
130130
}
131131

132+
// Converts a radiant patch to an obj object.
133+
public static ObjObject CreateFromPatch(string name, Patch patch)
134+
{
135+
Vertex[] vertices = patch.GetVertices();
136+
Face[] faces = CreateFaces(patch.Grid);
137+
138+
return new ObjObject(name, vertices, faces);
139+
}
140+
132141
// Create normals of the object based on the clipping plane intersections.
133142
private static Vector[] CreateNormals(ClippingPlane[] planes)
134143
{
@@ -347,5 +356,25 @@ private static bool VerifyNormal(Face face, Vector normal)
347356
return true;
348357
return false;
349358
}
359+
360+
// Creates faces from a grid of vertices.
361+
private static Face[] CreateFaces(Vertex[][] grid)
362+
{
363+
List<Face> faces = new List<Face>();
364+
365+
for (int x = 0; x < grid.Length; ++x)
366+
{
367+
for (int y = 0; y < grid[x].Length; ++y)
368+
{
369+
if (x + 1 < grid.Length && y + 1 < grid[x].Length)
370+
{
371+
faces.Add(new Face(grid[x][y], grid[x+1][y], grid[x][y+1]));
372+
faces.Add(new Face(grid[x][y+1], grid[x+1][y], grid[x+1][y+1]));
373+
}
374+
}
375+
}
376+
377+
return faces.ToArray();
378+
}
350379
}
351380
}

src/Patch.cs

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text.RegularExpressions;
4+
5+
namespace RadiantMapToWavefrontObj
6+
{
7+
public class Patch
8+
{
9+
public Vertex[][] Grid { get; private set; }
10+
11+
private int _x;
12+
private int _y;
13+
14+
public Vertex[] this[int index]
15+
{
16+
get => Grid[index];
17+
set => Grid[index] = value;
18+
}
19+
20+
// Constructor for a patch.
21+
public Patch(int width, int height)
22+
{
23+
Grid = new Vertex[width][];
24+
25+
for (int i = 0; i < Grid.Length; ++i)
26+
{
27+
Grid[i] = new Vertex[height];
28+
for (int j = 0; j < Grid[i].Length; ++j)
29+
Grid[i][j] = null;
30+
}
31+
}
32+
33+
// Collect all vertices and return them.
34+
public Vertex[] GetVertices()
35+
{
36+
List<Vertex> vertices = new List<Vertex>();
37+
38+
foreach (Vertex[] row in Grid)
39+
{
40+
foreach (Vertex vert in row)
41+
vertices.Add(vert);
42+
}
43+
44+
return vertices.ToArray();
45+
}
46+
47+
// Adds a vertex to the grid in the next available slot.
48+
public void Add(Vertex vertex)
49+
{
50+
Grid[_y][_x] = vertex;
51+
52+
if (_x < Grid[0].Length-1)
53+
_x++;
54+
else
55+
{
56+
_x = 0;
57+
if (_y < Grid.Length - 1)
58+
_y++;
59+
else
60+
_y = 0;
61+
}
62+
}
63+
64+
// Creates a radiant patch from a piece of code.
65+
public static Patch CreateFromCode(string[] code)
66+
{
67+
string sizePattern = @"(\s+)?\(\s?(\d+)\s(\d+)\s(\d+)\s(\d+)\s(\d+)(\s(\d+)\s(\d+))?\s?\)"; //width,height [2,3]
68+
Regex sizeRegex = new Regex(sizePattern, RegexOptions.IgnoreCase);
69+
70+
Patch patch = null;
71+
72+
int line = 0;
73+
74+
while (line < code.Length)
75+
{
76+
Match m = sizeRegex.Match(code[line]);
77+
++line;
78+
if (m.Success)
79+
{
80+
patch = new Patch(int.Parse(m.Groups[2].ToString()), int.Parse(m.Groups[3].ToString()));
81+
break;
82+
}
83+
}
84+
85+
string num = @"-?\d+(\.\d+)?";
86+
string vertex = @"(\(\s?(" + num + @")\s(" + num + @")\s(" + num + @")\s(" //x,y,z [2,4,6]
87+
+ num + @")\s(" + num + @")\s(" //patchDef2
88+
+ "(" + num + @")\s(" + num + @")\s(" + num + @")\s(" + num + @")\s(" + num + @"))?\s?\))"; //patchDef3
89+
90+
string pattern = vertex;
91+
92+
Regex regex = new Regex(pattern, RegexOptions.IgnoreCase);
93+
94+
while (line < code.Length)
95+
{
96+
MatchCollection m = regex.Matches(code[line]);
97+
++line;
98+
if (m.Count > 0)
99+
{
100+
for (int i = 0; i < m.Count; ++i)
101+
{
102+
Vertex v = new Vertex(-Double.Parse(m[i].Groups[2].ToString(), System.Globalization.CultureInfo.InvariantCulture),
103+
-Double.Parse(m[i].Groups[4].ToString(), System.Globalization.CultureInfo.InvariantCulture),
104+
-Double.Parse(m[i].Groups[6].ToString(), System.Globalization.CultureInfo.InvariantCulture));
105+
106+
if (patch != null)
107+
patch.Add(v);
108+
}
109+
}
110+
}
111+
112+
return patch;
113+
}
114+
}
115+
}

src/RadiantMap.cs

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,33 @@
1-
using System.Collections.Generic;
1+
using System;
2+
using System.Collections.Generic;
23
using System.IO;
34

45
namespace RadiantMapToWavefrontObj
56
{
67
public class RadiantMap
78
{
8-
public readonly Brush[] Brushes;
9+
private List<Brush> _brushes;
10+
private List<Patch> _patches;
11+
public Brush[] Brushes => _brushes.ToArray();
12+
public Patch[] Patches => _patches.ToArray();
913

1014
// Constructor that creates a radiant map object.
11-
public RadiantMap(Brush[] brushes)
15+
public RadiantMap()
1216
{
13-
Brushes = brushes;
17+
_brushes = new List<Brush>();
18+
_patches = new List<Patch>();
19+
}
20+
21+
// Adds a brush to the radiant map.
22+
public void Add(Brush brush)
23+
{
24+
_brushes.Add(brush);
25+
}
26+
27+
// Adds a patch to the radiant map.
28+
public void Add(Patch patch)
29+
{
30+
_patches.Add(patch);
1431
}
1532

1633
// Returns a string format of the entire radiant map.
@@ -34,8 +51,10 @@ public static RadiantMap Parse(string path)
3451
string[] content = File.ReadAllLines(path);
3552
bool started = false;
3653
bool inBrush = false;
54+
bool inPatch = false;
3755
List<string> brushLines = null;
38-
List<Brush> brushes = new List<Brush>();
56+
57+
RadiantMap map = new RadiantMap();
3958

4059
for (int i = 0; i < content.Length; ++i)
4160
{
@@ -45,21 +64,29 @@ public static RadiantMap Parse(string path)
4564

4665
if (started)
4766
{
48-
if (content[i][0] == '{')
67+
if (content[i].Contains("{"))
4968
{
5069
if (!inBrush)
5170
{
5271
inBrush = true;
5372
brushLines = new List<string>();
73+
brushLines.Add(content[i]);
5474
}
75+
else if (!inPatch)
76+
inPatch = true;
5577
else
5678
return null;
5779
}
58-
else if (content[i][0] == '}')
80+
else if (content[i].Contains("}"))
5981
{
60-
if (inBrush)
82+
if (inPatch)
83+
{
84+
map.Add(Patch.CreateFromCode(brushLines.ToArray()));
85+
inPatch = false;
86+
}
87+
else if (inBrush)
6188
{
62-
brushes.Add(Brush.CreateFromCode(brushLines.ToArray()));
89+
map.Add(Brush.CreateFromCode(brushLines.ToArray()));
6390
inBrush = false;
6491
brushLines = new List<string>();
6592
}
@@ -77,7 +104,7 @@ public static RadiantMap Parse(string path)
77104

78105
}
79106

80-
return new RadiantMap(brushes.ToArray());
107+
return map;
81108
}
82109
}
83110
}

src/RadiantMapToWavefrontObj.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@
108108
<Compile Include="ArrayExtension.cs" />
109109
<Compile Include="Brush.cs" />
110110
<Compile Include="ClippingPlane.cs" />
111+
<Compile Include="Patch.cs" />
111112
<Compile Include="Plane.cs" />
112113
<Compile Include="Edge.cs" />
113114
<Compile Include="Face.cs" />

src/WavefrontObj.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,13 @@ public static WavefrontObj CreateFromRadiantMap(RadiantMap map)
7474
objects.Add(obj);
7575
}
7676

77+
for (int i = 0; i < map.Patches.Length; ++i)
78+
{
79+
Patch patch = map.Patches[i];
80+
ObjObject obj = ObjObject.CreateFromPatch("Patch_" + i, patch);
81+
objects.Add(obj);
82+
}
83+
7784
return new WavefrontObj(objects.ToArray());
7885
}
7986
}

0 commit comments

Comments
 (0)