Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion Crash.UI/Properties/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Crash.UI/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -357,4 +357,7 @@
<data name="NSFController_AcShowLevelZones" xml:space="preserve">
<value>Show All Level Zones</value>
</data>
<data name="NSFController_AcExportScenery" xml:space="preserve">
<value>Export all scenery to OBJ</value>
</data>
</root>
41 changes: 0 additions & 41 deletions Crash/Formats/Crash Formats/Animation/OldFrame.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,46 +128,5 @@ public byte[] Save()
}
return data;
}

public byte[] ToOBJ(OldModelEntry model)
{
long xorigin = 0;
long yorigin = 0;
long zorigin = 0;
//foreach (OldFrameVertex vertex in vertices)
//{
// xorigin += vertex.X;
// yorigin += vertex.Y;
// zorigin += vertex.Z;
//}
//xorigin /= vertices.Count;
//yorigin /= vertices.Count;
//zorigin /= vertices.Count;
xorigin -= XOffset;
yorigin -= YOffset;
zorigin -= ZOffset;
using (MemoryStream stream = new MemoryStream())
{
using (StreamWriter obj = new StreamWriter(stream))
{
obj.WriteLine("# Vertices");
foreach (OldFrameVertex vertex in vertices)
{
obj.WriteLine("v {0} {1} {2}", vertex.X - xorigin, vertex.Y - yorigin, vertex.Z - zorigin);
}
foreach (OldFrameVertex vertex in vertices)
{
obj.WriteLine("vn {0} {1} {2}", vertex.NormalX / 127.0, vertex.NormalY / 127.0, vertex.NormalZ / 127.0);
}
obj.WriteLine();
obj.WriteLine("# Polygons");
foreach (OldModelPolygon polygon in model.Polygons)
{
obj.WriteLine("f {0}//{0} {1}//{1} {2}//{2}", polygon.VertexA / 6 + 1, polygon.VertexB / 6 + 1, polygon.VertexC / 6 + 1);
}
}
return stream.ToArray();
}
}
}
}
237 changes: 0 additions & 237 deletions Crash/Formats/Crash Formats/Scenery/SceneryEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,242 +104,5 @@ public override UnprocessedEntry Unprocess()
}
return new UnprocessedEntry(items, EID, Type);
}

public byte[] ToOBJ()
{
using (MemoryStream stream = new MemoryStream())
{
using (StreamWriter obj = new StreamWriter(stream))
{
obj.WriteLine("# Vertices");
foreach (SceneryVertex vertex in vertices)
{
if (vertex.Color < Colors.Count)
{
SceneryColor color = Colors[vertex.Color];
obj.WriteLine("v {0} {1} {2} {3} {4} {5}", vertex.X + XOffset / 16, vertex.Y + YOffset / 16, vertex.Z + ZOffset / 16, color.Red / 255.0, color.Green / 255.0, color.Blue / 255.0);
}
else
{
obj.WriteLine("v {0} {1} {2}", vertex.X + XOffset / 16, vertex.Y + YOffset / 16, vertex.Z + ZOffset / 16);
}
}
obj.WriteLine();
obj.WriteLine("# Triangles");
foreach (SceneryTriangle triangle in triangles)
{
obj.WriteLine("f {0} {1} {2}", triangle.VertexA + 1, triangle.VertexB + 1, triangle.VertexC + 1);
}
obj.WriteLine();
obj.WriteLine("# Quads");
foreach (SceneryQuad quad in quads)
{
obj.WriteLine("f {0} {1} {2} {3}", quad.VertexA + 1, quad.VertexB + 1, quad.VertexC + 1, quad.VertexD + 1);
}
}
return stream.ToArray();
}
}

public byte[] ToPLY()
{
using (MemoryStream stream = new MemoryStream())
{
using (StreamWriter ply = new StreamWriter(stream))
{
int polycount = 0;
foreach (SceneryTriangle triangle in triangles)
{
if (triangle.VertexA < vertices.Count - 1 && triangle.VertexB < vertices.Count - 1 && triangle.VertexC < vertices.Count - 1)
{
++polycount;
}
}
foreach (SceneryQuad quad in quads)
{
if (quad.VertexA < vertices.Count - 1 && quad.VertexB < vertices.Count - 1 && quad.VertexC < vertices.Count - 1 && quad.VertexD < vertices.Count - 1)
{
++polycount;
}
}
ply.WriteLine("ply");
ply.WriteLine("format ascii 1.0");
ply.WriteLine("element vertex {0}", Vertices.Count);
ply.WriteLine("property int x");
ply.WriteLine("property int y");
ply.WriteLine("property int z");
ply.WriteLine("property uchar red");
ply.WriteLine("property uchar green");
ply.WriteLine("property uchar blue");
ply.WriteLine("element face {0}", polycount);
ply.WriteLine("property list uchar int vertex_index");
ply.WriteLine("end_header");
foreach (SceneryVertex vertex in vertices)
{
if (vertex.Color < Colors.Count)
{
SceneryColor color = Colors[vertex.Color];
ply.WriteLine("{0} {1} {2} {3} {4} {5}", vertex.X + XOffset / 16, vertex.Y + YOffset / 16, vertex.Z + ZOffset / 16, color.Red, color.Green, color.Blue);
}
else
{
ply.WriteLine("{0} {1} {2} 255 0 255", vertex.X + XOffset / 16, vertex.Y + YOffset / 16, vertex.Z + ZOffset / 16);
}
}
foreach (SceneryTriangle triangle in triangles)
{
if (triangle.VertexA < vertices.Count - 1 && triangle.VertexB < vertices.Count - 1 && triangle.VertexC < vertices.Count - 1)
{
ply.WriteLine("3 {0} {1} {2}", triangle.VertexA, triangle.VertexB, triangle.VertexC);
}
}
foreach (SceneryQuad quad in quads)
{
if (quad.VertexA < vertices.Count - 1 && quad.VertexB < vertices.Count - 1 && quad.VertexC < vertices.Count - 1 && quad.VertexD < vertices.Count - 1)
{
ply.WriteLine("4 {0} {1} {2} {3}", quad.VertexA, quad.VertexB, quad.VertexC, quad.VertexD);
}
}
}
return stream.ToArray();
}
}

/*public byte[] ToCOLLADA()
{
using (MemoryStream stream = new MemoryStream())
{
using (StreamWriter textwriter = new StreamWriter(stream))
using (XmlTextWriter xmlwriter = new XmlTextWriter(textwriter))
{
xmlwriter.WriteStartDocument();
xmlwriter.WriteStartElement("COLLADA");
xmlwriter.WriteAttributeString("xmlns", "http://www.collada.org/2005/11/COLLADASchema");
xmlwriter.WriteAttributeString("version", "1.4.1");
xmlwriter.WriteStartElement("library_geometries");
xmlwriter.WriteStartElement("geometry");
xmlwriter.WriteStartElement("mesh");
xmlwriter.WriteStartElement("source");
xmlwriter.WriteAttributeString("id", "positions");
xmlwriter.WriteStartElement("float_array");
xmlwriter.WriteAttributeString("id", "positions-array");
xmlwriter.WriteAttributeString("count", (vertices.Count * 3).ToString());
foreach (NewSceneryVertex vertex in vertices)
{
xmlwriter.WriteValue(vertex.X + XOffset / 4);
xmlwriter.WriteWhitespace(" ");
xmlwriter.WriteValue(vertex.Y + YOffset / 4);
xmlwriter.WriteWhitespace(" ");
xmlwriter.WriteValue(vertex.Z + ZOffset / 4);
xmlwriter.WriteWhitespace(" ");
}
xmlwriter.WriteEndElement();
xmlwriter.WriteStartElement("technique_common");
xmlwriter.WriteStartElement("accessor");
xmlwriter.WriteAttributeString("source", "#positions-array");
xmlwriter.WriteAttributeString("count", vertices.Count.ToString());
xmlwriter.WriteAttributeString("stride", "3");
xmlwriter.WriteStartElement("param");
xmlwriter.WriteAttributeString("name", "X");
xmlwriter.WriteAttributeString("type", "float");
xmlwriter.WriteEndElement();
xmlwriter.WriteStartElement("param");
xmlwriter.WriteAttributeString("name", "Y");
xmlwriter.WriteAttributeString("type", "float");
xmlwriter.WriteEndElement();
xmlwriter.WriteStartElement("param");
xmlwriter.WriteAttributeString("name", "Y");
xmlwriter.WriteAttributeString("type", "float");
xmlwriter.WriteEndElement();
xmlwriter.WriteEndElement();
xmlwriter.WriteEndElement();
xmlwriter.WriteEndElement();
xmlwriter.WriteStartElement("source");
xmlwriter.WriteAttributeString("id", "colors");
xmlwriter.WriteStartElement("float_array");
xmlwriter.WriteAttributeString("id", "colors-array");
xmlwriter.WriteAttributeString("count", (vertices.Count * 3).ToString());
foreach (NewSceneryVertex vertex in vertices)
{
if (vertex.Color < Colors.Count)
{
SceneryColor color = Colors[vertex.Color];
xmlwriter.WriteValue(color.Red / 256.0);
xmlwriter.WriteWhitespace(" ");
xmlwriter.WriteValue(color.Green / 256.0);
xmlwriter.WriteWhitespace(" ");
xmlwriter.WriteValue(color.Blue / 256.0);
xmlwriter.WriteWhitespace(" ");
}
else
{
xmlwriter.WriteValue(256.0 / 256.0);
xmlwriter.WriteWhitespace(" ");
xmlwriter.WriteValue(0 / 256.0);
xmlwriter.WriteWhitespace(" ");
xmlwriter.WriteValue(256.0 / 256.0);
xmlwriter.WriteWhitespace(" ");
}
}
xmlwriter.WriteEndElement();
xmlwriter.WriteStartElement("technique_common");
xmlwriter.WriteStartElement("accessor");
xmlwriter.WriteAttributeString("source", "#colors-array");
xmlwriter.WriteAttributeString("count", vertices.Count.ToString());
xmlwriter.WriteAttributeString("stride", "3");
xmlwriter.WriteStartElement("param");
xmlwriter.WriteAttributeString("name", "R");
xmlwriter.WriteAttributeString("type", "float");
xmlwriter.WriteEndElement();
xmlwriter.WriteStartElement("param");
xmlwriter.WriteAttributeString("name", "G");
xmlwriter.WriteAttributeString("type", "float");
xmlwriter.WriteEndElement();
xmlwriter.WriteStartElement("param");
xmlwriter.WriteAttributeString("name", "B");
xmlwriter.WriteAttributeString("type", "float");
xmlwriter.WriteEndElement();
xmlwriter.WriteEndElement();
xmlwriter.WriteEndElement();
xmlwriter.WriteEndElement();
xmlwriter.WriteStartElement("vertices");
xmlwriter.WriteAttributeString("id", "vertices");
xmlwriter.WriteStartElement("input");
xmlwriter.WriteAttributeString("semantic", "POSITION");
xmlwriter.WriteAttributeString("source", "positions");
xmlwriter.WriteEndElement();
xmlwriter.WriteStartElement("input");
xmlwriter.WriteAttributeString("semantic", "COLOR");
xmlwriter.WriteAttributeString("source", "colors");
xmlwriter.WriteEndElement();
xmlwriter.WriteEndElement();
xmlwriter.WriteStartElement("triangles");
xmlwriter.WriteAttributeString("count", triangles.Count.ToString());
xmlwriter.WriteStartElement("input");
xmlwriter.WriteAttributeString("semantic", "VERTEX");
xmlwriter.WriteAttributeString("source", "vertices");
xmlwriter.WriteAttributeString("offset", "0");
xmlwriter.WriteEndElement();
xmlwriter.WriteStartElement("p");
foreach (SceneryTriangle triangle in triangles)
{
xmlwriter.WriteValue(triangle.VertexA);
xmlwriter.WriteWhitespace(" ");
xmlwriter.WriteValue(triangle.VertexB);
xmlwriter.WriteWhitespace(" ");
xmlwriter.WriteValue(triangle.VertexC);
xmlwriter.WriteWhitespace(" ");
}
xmlwriter.WriteEndElement();
xmlwriter.WriteEndElement();
xmlwriter.WriteEndElement();
xmlwriter.WriteEndElement();
xmlwriter.WriteEndElement();
xmlwriter.WriteEndElement();
xmlwriter.WriteEndDocument();
}
return stream.ToArray();
}
}*/
}
}
2 changes: 2 additions & 0 deletions CrashEdit.Main.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
<TargetFramework>net8.0-windows</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
</PropertyGroup>


Expand Down
24 changes: 24 additions & 0 deletions CrashEdit/Controllers/Animation/AnimationEntryController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ public sealed class AnimationEntryController : EntryController
public AnimationEntryController(AnimationEntry animationentry, SubcontrollerGroup parentGroup) : base(animationentry, parentGroup)
{
AnimationEntry = animationentry;
AddMenu ("Export as OBJ", Menu_Export_OBJ);
}

public override bool EditorAvailable => true;
Expand All @@ -18,5 +19,28 @@ public override Control CreateEditor()
}

public AnimationEntry AnimationEntry { get; }

private void Menu_Export_OBJ ()
{
if (!FileUtil.SelectSaveFile (out string output, FileFilters.OBJ, FileFilters.Any))
return;

// modify the path to add a number before the extension
string ext = Path.GetExtension (output);
string filename = Path.GetFileNameWithoutExtension (output);
string path = Path.GetDirectoryName (output);

int id = 0;
int count = Modern.SubcontrollerGroups.SelectMany(x => x.Members).Count().ToString().Length;

foreach (Controller node in Modern.SubcontrollerGroups.SelectMany (x => x.Members))
{
if (node.Legacy is not FrameController frame)
continue;

frame.ToOBJ (path, filename + id.ToString().PadLeft (count, '0'));
id++;
}
}
}
}
Loading