Skip to content

Commit bf86445

Browse files
committed
fixes from testing, edge case handling
1 parent e599d42 commit bf86445

File tree

9 files changed

+377
-50
lines changed

9 files changed

+377
-50
lines changed

DenizenModelsConverter/BBModel.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@ public class BBModel
2828

2929
public List<Outliner> Outlines = new();
3030

31+
public HashSet<Guid> DiscardedIDs = new();
32+
33+
public Element GetElement(Guid id)
34+
{
35+
return Elements.FirstOrDefault(e => e.UUID == id);
36+
}
37+
3138
public class Element
3239
{
3340
public string Name;
@@ -66,6 +73,10 @@ public class Texture
6673
public Guid UUID;
6774

6875
public byte[] RawImageBytes;
76+
77+
public string CorrectedFullPath;
78+
79+
public int Width, Height;
6980
}
7081

7182
public class Outliner
@@ -74,6 +85,8 @@ public class Outliner
7485

7586
public DoubleVector Origin;
7687

88+
public DoubleVector Rotation;
89+
7790
public Guid UUID;
7891

7992
public List<Guid> Children = new();

DenizenModelsConverter/BBModelReader.cs

Lines changed: 69 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.IO;
34
using System.Linq;
45
using System.Text;
56
using System.Threading.Tasks;
7+
using System.Drawing;
8+
using System.Drawing.Imaging;
69
using FreneticUtilities.FreneticExtensions;
710
using FreneticUtilities.FreneticToolkit;
811
using Newtonsoft.Json;
@@ -12,14 +15,9 @@ namespace DenizenModelsConverter
1215
{
1316
public static class BBModelReader
1417
{
15-
public static bool Verbose = false;
16-
1718
public static void Debug(string text)
1819
{
19-
if (Verbose)
20-
{
21-
Console.WriteLine($"[Debug] {text}");
22-
}
20+
Program.Debug(text);
2321
}
2422

2523
public static BBModel Interpret(string fileContent)
@@ -40,6 +38,7 @@ public static BBModel Interpret(string fileContent)
4038
JArray textures = (JArray)data["textures"];
4139
JArray outliners = (JArray)data["outliner"];
4240
JArray animations = (JArray)data["animations"];
41+
Dictionary<string, int> elementNames = new(), outlineNames = new();
4342
if (elements is not null)
4443
{
4544
Debug("Contains elements");
@@ -48,11 +47,19 @@ public static BBModel Interpret(string fileContent)
4847
JObject jFaces = (JObject)jElement["faces"];
4948
string name = (string)jElement.GetRequired("name");
5049
string type = jElement.GetString("type", "cube");
50+
Guid id = Guid.Parse((string)jElement.GetRequired("uuid"));
5151
if (type != "cube")
5252
{
53-
Debug($"Skip element of type '{type}' with name '{name}'");
53+
Debug($"Skip element of type '{type}' with name '{name}' and id {id}");
54+
result.DiscardedIDs.Add(id);
5455
continue;
5556
}
57+
int nameUsed = elementNames.GetValueOrDefault(name, 0);
58+
elementNames[name] = nameUsed + 1;
59+
if (nameUsed > 0)
60+
{
61+
name += (nameUsed + 1);
62+
}
5663
BBModel.Element element = new()
5764
{
5865
Name = name,
@@ -71,9 +78,9 @@ public static BBModel Interpret(string fileContent)
7178
Up = ParseFaceFromJson(jFaces.GetRequired("up")),
7279
Down = ParseFaceFromJson(jFaces.GetRequired("down")),
7380
Type = type,
74-
UUID = Guid.Parse((string)jElement.GetRequired("uuid"))
81+
UUID = id
7582
};
76-
Debug($"Read element {element.Name}");
83+
Debug($"Read element {element.Name} as id {element.UUID}");
7784
result.Elements.Add(element);
7885
}
7986
}
@@ -101,6 +108,13 @@ public static BBModel Interpret(string fileContent)
101108
throw new Exception($"Cannot read model - texture {texture.Name} contains source data that isn't the expected base64 png.");
102109
}
103110
texture.RawImageBytes = Convert.FromBase64String(sourceTex.After("data:image/png;base64,"));
111+
#pragma warning disable CA1416 // Validate platform compatibility
112+
using (Image image = Image.FromStream(new MemoryStream(texture.RawImageBytes)))
113+
{
114+
texture.Width = image.Width;
115+
texture.Height = image.Height;
116+
}
117+
#pragma warning restore CA1416 // Validate platform compatibility
104118
Debug($"Read texture {texture.Name}");
105119
result.Textures.Add(texture);
106120
}
@@ -110,7 +124,7 @@ public static BBModel Interpret(string fileContent)
110124
Debug("contains outliners");
111125
foreach (JObject jOutliner in outliners)
112126
{
113-
ReadOutliner(result, jOutliner);
127+
ReadOutliner(result, jOutliner, outlineNames);
114128
}
115129
}
116130
if (animations is not null)
@@ -160,11 +174,20 @@ public static BBModel Interpret(string fileContent)
160174
return result;
161175
}
162176

163-
public static BBModel.Outliner ReadOutliner(BBModel model, JObject jOutliner)
177+
public static HashSet<double> AcceptableRotations = new() { 0, 22.5, 45, -22.5, -45 };
178+
179+
public static BBModel.Outliner ReadOutliner(BBModel model, JObject jOutliner, Dictionary<string, int> names)
164180
{
181+
string name = (string)jOutliner.GetRequired("name");
182+
int nameUsed = names.GetValueOrDefault(name, 0);
183+
names[name] = nameUsed + 1;
184+
if (nameUsed > 0)
185+
{
186+
name += (nameUsed + 1);
187+
}
165188
BBModel.Outliner outline = new()
166189
{
167-
Name = (string)jOutliner.GetRequired("name"),
190+
Name = name,
168191
Origin = ParseDVecFromArr(jOutliner.GetRequired("origin")),
169192
UUID = Guid.Parse((string)jOutliner.GetRequired("uuid")),
170193
// Ignore ik_enabled, ik_chain_length, export, isOpen, locked, visibility, autouv
@@ -173,11 +196,42 @@ public static BBModel.Outliner ReadOutliner(BBModel model, JObject jOutliner)
173196
{
174197
if (child.Type == JTokenType.String)
175198
{
176-
outline.Children.Add(Guid.Parse((string)child));
199+
Guid id = Guid.Parse((string)child);
200+
BBModel.Element element = model.GetElement(id);
201+
if (element is null)
202+
{
203+
if (model.DiscardedIDs.Contains(id))
204+
{
205+
continue;
206+
}
207+
throw new Exception($"Cannot find required element {id} for outline {outline.Name}");
208+
}
209+
if (AcceptableRotations.Contains(element.Rotation.X) && AcceptableRotations.Contains(element.Rotation.Y) && AcceptableRotations.Contains(element.Rotation.Z))
210+
{
211+
outline.Children.Add(id);
212+
}
213+
else
214+
{
215+
BBModel.Outliner specialSideOutline = new()
216+
{
217+
Name = $"{outline.Name}_auto_{element.Name}",
218+
Origin = outline.Origin + element.Origin,
219+
Rotation = element.Rotation,
220+
UUID = Guid.NewGuid(),
221+
};
222+
// TODO: Is this shift needed?
223+
//element.From -= element.Origin;
224+
//element.To -= element.Origin;
225+
element.Rotation = new DoubleVector();
226+
element.Origin = new DoubleVector();
227+
specialSideOutline.Children.Add(element.UUID);
228+
model.Outlines.Add(specialSideOutline);
229+
outline.Paired.Add(specialSideOutline.UUID);
230+
}
177231
}
178232
else
179233
{
180-
BBModel.Outliner subLine = ReadOutliner(model, (JObject) child);
234+
BBModel.Outliner subLine = ReadOutliner(model, (JObject) child, names);
181235
outline.Paired.Add(subLine.UUID);
182236
outline.Paired.AddRange(subLine.Paired);
183237
}
@@ -208,7 +262,7 @@ public static BBModel.Element.Face ParseFaceFromJson(JToken jVal)
208262
TextureID = (int)jObj.GetRequired("texture"),
209263
TexCoord = new BBModel.Element.Face.UV()
210264
{
211-
ULow = (int)uv[0], // TODO: Validate this ordering
265+
ULow = (int)uv[0],
212266
VLow = (int)uv[1],
213267
UHigh = (int)uv[2],
214268
VHigh = (int)uv[3]

DenizenModelsConverter/DenizenModelsConverter.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
<ItemGroup>
99
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
10+
<PackageReference Include="System.Drawing.Common" Version="6.0.0" />
1011
</ItemGroup>
1112

1213
<ItemGroup>

DenizenModelsConverter/DoubleVector.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,20 @@ public DoubleVector(double x, double y, double z)
2323
Y = y;
2424
Z = z;
2525
}
26+
27+
public static DoubleVector operator -(in DoubleVector v1, in DoubleVector v2)
28+
{
29+
return new DoubleVector(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z);
30+
}
31+
32+
public static DoubleVector operator +(in DoubleVector v1, in DoubleVector v2)
33+
{
34+
return new DoubleVector(v1.X + v2.X, v1.Y + v2.Y, v1.Z + v2.Z);
35+
}
36+
37+
public string ToDenizenString()
38+
{
39+
return $"{X},{Y},{Z}";
40+
}
2641
}
2742
}

DenizenModelsConverter/IntegerVector.cs

Lines changed: 0 additions & 27 deletions
This file was deleted.

DenizenModelsConverter/MinecraftModelMaker.cs

Lines changed: 86 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,98 @@
33
using System.Linq;
44
using System.Text;
55
using System.Threading.Tasks;
6+
using FreneticUtilities.FreneticExtensions;
7+
using FreneticUtilities.FreneticToolkit;
8+
using Newtonsoft.Json;
9+
using Newtonsoft.Json.Linq;
610

711
namespace DenizenModelsConverter
812
{
913
public class MinecraftModelMaker
1014
{
11-
public static string CreateModelFor(BBModel model, string outline)
15+
public static string CreateModelFor(BBModel model, BBModel.Outliner outline)
1216
{
13-
return null;
17+
JObject jout = new(), textures = new(), group = new();
18+
JArray groups = new(), elements = new();
19+
JArray childrenList = new();
20+
foreach (BBModel.Texture texture in model.Textures)
21+
{
22+
textures.Add(texture.ID, texture.CorrectedFullPath);
23+
if (texture.Particle)
24+
{
25+
textures.Add("particle", texture.CorrectedFullPath);
26+
}
27+
}
28+
int id = 0;
29+
bool any = false;
30+
foreach (BBModel.Element element in model.Elements)
31+
{
32+
if (outline.Children.Contains(element.UUID))
33+
{
34+
any = true;
35+
JObject jElement = new();
36+
jElement.Add("name", element.Name);
37+
jElement.Add("from", DVecToArray(element.From));
38+
jElement.Add("to", DVecToArray(element.To));
39+
JObject rotation = new();
40+
rotation.Add("origin", DVecToArray(element.Origin));
41+
if (element.Rotation.X != 0)
42+
{
43+
rotation.Add("angle", element.Rotation.X);
44+
rotation.Add("axis", "x");
45+
}
46+
else if (element.Rotation.Z != 0)
47+
{
48+
rotation.Add("angle", element.Rotation.Z);
49+
rotation.Add("axis", "z");
50+
}
51+
else
52+
{
53+
rotation.Add("angle", element.Rotation.Y);
54+
rotation.Add("axis", "y");
55+
}
56+
jElement.Add("rotation", rotation);
57+
JObject faces = new();
58+
faces.Add("north", FaceToJObj(element.North, model));
59+
faces.Add("south", FaceToJObj(element.South, model));
60+
faces.Add("east", FaceToJObj(element.East, model));
61+
faces.Add("west", FaceToJObj(element.West, model));
62+
faces.Add("up", FaceToJObj(element.Up, model));
63+
faces.Add("down", FaceToJObj(element.Down, model));
64+
jElement.Add("faces", faces);
65+
elements.Add(jElement);
66+
childrenList.Add(id++);
67+
}
68+
}
69+
if (!any)
70+
{
71+
return null;
72+
}
73+
group.Add("name", outline.Name);
74+
group.Add("origin", DVecToArray(outline.Origin));
75+
group.Add("color", 0);
76+
group.Add("children", childrenList);
77+
groups.Add(group);
78+
jout.Add("textures", textures);
79+
jout.Add("elements", elements);
80+
jout.Add("groups", groups);
81+
return jout.ToString();
82+
}
83+
84+
public static JObject FaceToJObj(BBModel.Element.Face face, BBModel model)
85+
{
86+
BBModel.Texture texture = model.Textures[face.TextureID];
87+
float relativeU = 16f / texture.Width;
88+
float relativeV = 16f / texture.Height;
89+
JObject output = new();
90+
output.Add("uv", new JArray(face.TexCoord.ULow * relativeU, face.TexCoord.VLow * relativeV, face.TexCoord.UHigh * relativeU, face.TexCoord.VHigh * relativeV));
91+
output.Add("texture", $"#{face.TextureID}");
92+
return output;
93+
}
94+
95+
public static JArray DVecToArray(DoubleVector dvec)
96+
{
97+
return new JArray(dvec.X, dvec.Y, dvec.Z);
1498
}
1599
}
16100
}

0 commit comments

Comments
 (0)