Remove CSM.cs and 3DSUtil and created reader/writer for 3ds textures

This commit is contained in:
miku-666
2023-04-10 11:29:18 +02:00
parent 60fbdfe795
commit 04b0b66f67
8 changed files with 175 additions and 234 deletions

View File

@@ -1,91 +0,0 @@
using System;
using System.Drawing;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PckStudio.Models;
namespace PckStudio.Classes
{
class CSM
{
//Part Name
//Part Parent(HEAD, BODY, LEG0, LEG1, ARM0, ARM1)
//Part Name
//Position-X
//Position-Y
//Position-Z
//Size-X
//Size-Y
//Size-Z
//UV-Y
//UV-X
public static List<string> CSMBlock = new List<string>();
public static void TryParse(string CSM, MinecraftModelView modelView)
{
try
{
int i = 0;
string[] CSMLines = CSM.Split(new[] { "\n", "\r\n" }, StringSplitOptions.None);
foreach (string line in CSMLines)
{
if (i > 10)
{
GetModelPartFromCSM(CSMBlock, modelView);
CSMBlock.Clear();
i = 0;
}
CSMBlock.Add(line + "\n");
i++;
}
modelView.Invalidate();
}
catch { }
}
public static void GetModelPartFromCSM(List<string> CSM, MinecraftModelView modelView)
{
string PartName = CSM[0];
string PartParent = CSM[1];
string PartName2 = CSM[2];
int PositionX = int.Parse(CSM[3]);
int PositionY = int.Parse(CSM[4]);
int PositionZ = int.Parse(CSM[5]);
int SizeX = int.Parse(CSM[6]);
int SizeY = int.Parse(CSM[7]);
int SizeZ = int.Parse(CSM[8]);
int UVY = int.Parse(CSM[9]);
int UVX = int.Parse(CSM[10]);
//RenderBox
System.Drawing.Image source = Textures[0].Source;
Object3D object3D = new Box(source, new Rectangle(8, 0, 0x10, 8), new Rectangle(0, 8, 0x20, 8), new Point3D(0f, 0f, 0f), Effects.None);
Object3D object3D2 = new Box(source, new Rectangle(0x28, 0, 0x10, 8), new Rectangle(0x20, 8, 0x20, 8), new Point3D(0f, 0f, 0f), Effects.None);
Object3D object3D3 = new Box(source, new Rectangle(0x2C, 0x10, 8, 4), new Rectangle(0x28, 0x14, 0x20, 0xC), new Point3D(0f, 4f, 0f), Effects.FlipHorizontally);
//RenderGroup
Object3DGroup object3DGroup = new Object3DGroup();
object3D2.Scale = 1.16f;
object3DGroup.RotationOrder = RotationOrders.XY;
object3DGroup.MinDegrees1 = -80f;
object3DGroup.MaxDegrees1 = 80f;
object3DGroup.MinDegrees2 = -57f;
object3DGroup.MaxDegrees2 = 57f;
object3DGroup.Add(object3D);
object3DGroup.Add(object3D2);
object3DGroup.Position = new Point3D(0f, 8f, 0f);
object3DGroup.Origin = new Point3D(0f, -4f, 0f);
object3DGroup.RotationOrder = RotationOrders.XY;
modelView.AddDynamic(object3DGroup);
}
public static Texture[] Textures = new Texture[] { new Texture(Bitmap.FromFile(Environment.CurrentDirectory + "\\default.png")) };
}
}

View File

@@ -0,0 +1,94 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OMI.Workers;
using PckStudio.Classes._3ds;
using OMI;
namespace PckStudio.Classes.IO._3DST
{
internal class _3DSTextureReader : IDataFormatReader<Image>, IDataFormatReader
{
public Image FromFile(string filename)
{
if (File.Exists(filename))
{
Image img = null;
using (var fs = File.OpenRead(filename))
{
img = FromStream(fs);
}
return img;
}
throw new FileNotFoundException(filename);
}
public Image FromStream(Stream stream)
{
Image img = null;
using (var reader = new EndiannessAwareBinaryReader(stream, Encoding.ASCII, leaveOpen: true, Endianness.LittleEndian))
{
if (reader.ReadString(4) == "3DST")
{
const int offset = 32;
reader.ReadInt32(); // unknown value
_3DSTextureFormat format = reader.ReadInt32() switch
{
0 => _3DSTextureFormat.argb8,
1 => _3DSTextureFormat.rgb8,
2 => _3DSTextureFormat.rgba5551,
3 => _3DSTextureFormat.rgb8,
4 => _3DSTextureFormat.rgba4,
9 => _3DSTextureFormat.la4,
_ => _3DSTextureFormat.dontCare,
};
int width = reader.ReadInt32();
int height = reader.ReadInt32();
int bufferSize = CalcBufferSize(format, width, height);
stream.Seek(offset, SeekOrigin.Begin);
byte[] buffer = new byte[bufferSize];
reader.Read(buffer, 0, bufferSize);
img = TextureCodec.Decode(buffer, width, height, format);
img.RotateFlip(RotateFlipType.RotateNoneFlipY);
}
}
return img;
}
private static int CalcBufferSize(_3DSTextureFormat textureFormat, int width, int height)
{
switch (textureFormat)
{
case _3DSTextureFormat.argb8:
return width * height * 4;
case _3DSTextureFormat.rgb8:
return width * height * 3;
case _3DSTextureFormat.rgba5551:
case _3DSTextureFormat.rgb565:
case _3DSTextureFormat.rgba4:
case _3DSTextureFormat.la8:
case _3DSTextureFormat.hilo8:
return width * height * 2;
case _3DSTextureFormat.l8:
case _3DSTextureFormat.a8:
case _3DSTextureFormat.la4:
case _3DSTextureFormat.etc1a4:
return width * height;
case _3DSTextureFormat.l4:
case _3DSTextureFormat.a4:
case _3DSTextureFormat.etc1:
return width * height >> 1;
default:
throw new InvalidDataException("Invalid texture format on BCH!");
}
}
object IDataFormatReader.FromFile(string filename) => FromFile(filename);
object IDataFormatReader.FromStream(Stream stream) => FromStream(stream);
}
}

View File

@@ -0,0 +1,47 @@
using System;
using System.Drawing;
using System.IO;
using System.Text;
using OMI;
using OMI.Workers;
using PckStudio.Classes._3ds;
namespace PckStudio.Classes.IO._3DST
{
internal class _3DSTextureWriter : IDataFormatWriter
{
private Image _image;
private _3DSTextureFormat _format;
public _3DSTextureWriter(Image image, _3DSTextureFormat format = _3DSTextureFormat.argb8)
{
_image = image;
_format = format;
}
public void WriteToFile(string filename)
{
using(var fs = File.OpenWrite(filename))
{
WriteToStream(fs);
}
}
public void WriteToStream(Stream stream)
{
using (var writer = new EndiannessAwareBinaryWriter(stream, Encoding.ASCII, leaveOpen: true, Endianness.LittleEndian))
{
writer.WriteString("3DST"); // 0
writer.Write(2); // 4 unknown
writer.Write((int)_format); // 8
writer.Write(_image.Width); // 12
writer.Write(_image.Height); // 16
writer.Write(0); // 20
writer.Write(0); // 24
writer.Write(0); // 28
_image.RotateFlip(RotateFlipType.RotateNoneFlipY);
byte[] buffer = TextureCodec.Encode(new Bitmap(_image), _format);
stream.Write(buffer, 0, buffer.Length);
}
}
}
}

View File

@@ -2,14 +2,35 @@
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using PckStudio.Classes._3ds.Utils;
namespace PckStudio.Classes._3ds
{
/// <summary>
/// Format of the texture used on the PICA200.
/// </summary>
public enum _3DSTextureFormat
{
argb8 = 0,
rgb8 = 1,
rgba5551 = 2,
rgb565 = 3,
rgba4 = 4,
la8 = 5,
hilo8 = 6,
l8 = 7,
a8 = 8,
la4 = 9,
l4 = 0xa,
a4 = 0xb,
etc1 = 0xc,
etc1a4 = 0xd,
dontCare
}
class TextureCodec
{
private static int[] tileOrder = { 0, 1, 8, 9, 2, 3, 10, 11, 16, 17, 24, 25, 18, 19, 26, 27, 4, 5, 12, 13, 6, 7, 14, 15, 20, 21, 28, 29, 22, 23, 30, 31, 32, 33, 40, 41, 34, 35, 42, 43, 48, 49, 56, 57, 50, 51, 58, 59, 36, 37, 44, 45, 38, 39, 46, 47, 52, 53, 60, 61, 54, 55, 62, 63 };
private static int[,] etc1LUT = { { 2, 8, -2, -8 }, { 5, 17, -5, -17 }, { 9, 29, -9, -29 }, { 13, 42, -13, -42 }, { 18, 60, -18, -60 }, { 24, 80, -24, -80 }, { 33, 106, -33, -106 }, { 47, 183, -47, -183 } };
private static readonly int[] tileOrder = { 0, 1, 8, 9, 2, 3, 10, 11, 16, 17, 24, 25, 18, 19, 26, 27, 4, 5, 12, 13, 6, 7, 14, 15, 20, 21, 28, 29, 22, 23, 30, 31, 32, 33, 40, 41, 34, 35, 42, 43, 48, 49, 56, 57, 50, 51, 58, 59, 36, 37, 44, 45, 38, 39, 46, 47, 52, 53, 60, 61, 54, 55, 62, 63 };
private static readonly int[,] etc1LUT = { { 2, 8, -2, -8 }, { 5, 17, -5, -17 }, { 9, 29, -9, -29 }, { 13, 42, -13, -42 }, { 18, 60, -18, -60 }, { 24, 80, -24, -80 }, { 33, 106, -33, -106 }, { 47, 183, -47, -183 } };
private static class TextureConverter
{

View File

@@ -1,131 +0,0 @@
using System;
using System.Drawing;
using System.IO;
using System.Text;
namespace PckStudio.Classes._3ds.Utils
{
/// <summary>
/// Format of the texture used on the PICA200.
/// </summary>
public enum _3DSTextureFormat
{
argb8 = 0,
rgb8 = 1,
rgba5551 = 2,
rgb565 = 3,
rgba4 = 4,
la8 = 5,
hilo8 = 6,
l8 = 7,
a8 = 8,
la4 = 9,
l4 = 0xa,
a4 = 0xb,
etc1 = 0xc,
etc1a4 = 0xd,
dontCare
}
internal class _3DSUtil
{
private static string ReadString(Stream stream, int len)
{
byte[] buffer = new byte[len];
stream.Read(buffer, 0, len);
return Encoding.ASCII.GetString(buffer);
}
private static int ReadInt32(Stream stream)
{
byte[] buffer = new byte[4];
stream.Read(buffer, 0, 4);
return BitConverter.ToInt32(buffer, 0);
}
private static void WriteString(Stream stream, string s)
{
byte[] buffer = Encoding.ASCII.GetBytes(s);
stream.Write(buffer, 0, buffer.Length);
}
private static void WriteInt32(Stream stream, int value)
{
byte[] buffer = BitConverter.GetBytes(value);
stream.Write(buffer, 0, 4);
}
public static int CalcBufferSize(_3DSTextureFormat textureFormat, int width, int height)
{
switch (textureFormat)
{
case _3DSTextureFormat.argb8:
return width * height * 4;
case _3DSTextureFormat.rgb8:
return width * height * 3;
case _3DSTextureFormat.rgba5551:
case _3DSTextureFormat.rgb565:
case _3DSTextureFormat.rgba4:
case _3DSTextureFormat.la8:
case _3DSTextureFormat.hilo8:
return width * height * 2;
case _3DSTextureFormat.l8:
case _3DSTextureFormat.a8:
case _3DSTextureFormat.la4:
case _3DSTextureFormat.etc1a4:
return width * height;
case _3DSTextureFormat.l4:
case _3DSTextureFormat.a4:
case _3DSTextureFormat.etc1:
return width * height >> 1;
default:
throw new InvalidDataException("Invalid texture format on BCH!");
}
}
public static Image GetImageFrom3DST(Stream stream)
{
if (ReadString(stream, 4) == "3DST")
{
const int offset = 32;
stream.Seek(8L, SeekOrigin.Begin);
_3DSTextureFormat format = ReadInt32(stream) switch
{
0 => _3DSTextureFormat.argb8,
1 => _3DSTextureFormat.rgb8,
2 => _3DSTextureFormat.rgba5551,
3 => _3DSTextureFormat.rgb8,
4 => _3DSTextureFormat.rgba4,
9 => _3DSTextureFormat.la4,
_ => _3DSTextureFormat.dontCare,
};
int width = ReadInt32(stream);
int height = ReadInt32(stream);
int bufferSize = CalcBufferSize(format, width, height);
stream.Seek(offset, SeekOrigin.Begin);
byte[] buffer = new byte[bufferSize];
stream.Read(buffer, 0, bufferSize);
var img = TextureCodec.Decode(buffer, width, height, format);
img.RotateFlip(RotateFlipType.RotateNoneFlipY);
return img;
}
return null;
}
public static void SetImageTo3DST(Stream stream, Image source, _3DSTextureFormat format = _3DSTextureFormat.argb8)
{
// TODO: fix Encoding
WriteString(stream, "3DST"); // 0
WriteInt32(stream, 2); // 4 unknown
WriteInt32(stream, (int)format); // 8
WriteInt32(stream, source.Width); // 12
WriteInt32(stream, source.Height); // 16
WriteInt32(stream, 0); // 20
WriteInt32(stream, 0); // 24
WriteInt32(stream, 0); // 28
source.RotateFlip(RotateFlipType.RotateNoneFlipY);
byte[] buffer = TextureCodec.Encode(new Bitmap(source), format);
stream.Write(buffer, 0, buffer.Length);
}
}
}

View File

@@ -5,10 +5,10 @@ using System.Windows.Forms;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using PckStudio.Classes.Utils;
using PckStudio.Classes._3ds.Utils;
using OMI.Formats.Languages;
using OMI.Formats.Pck;
using PckStudio.Forms.Editor;
using PckStudio.Classes.IO._3DST;
namespace PckStudio
{
@@ -347,7 +347,8 @@ namespace PckStudio
{
using (var fs = File.OpenRead(ofdd.FileName))
{
CheckImage(_3DSUtil.GetImageFrom3DST(fs));
var reader = new _3DSTextureReader();
CheckImage(reader.FromStream(fs));
textSkinName.Text = Path.GetFileNameWithoutExtension(ofdd.FileName);
}
return;

View File

@@ -19,7 +19,6 @@ using PckStudio.Properties;
using PckStudio.Classes.FileTypes;
using PckStudio.Classes.Utils;
using PckStudio.Classes.Utils.ARC;
using PckStudio.Classes._3ds.Utils;
using PckStudio.Forms;
using PckStudio.Forms.Utilities;
using PckStudio.Forms.Editor;
@@ -27,6 +26,7 @@ using PckStudio.Forms.Additional_Popups.Animation;
using PckStudio.Forms.Additional_Popups;
using PckStudio.Classes.Misc;
using PckStudio.Classes.IO.PCK;
using PckStudio.Classes.IO._3DST;
namespace PckStudio
{
@@ -2069,11 +2069,11 @@ namespace PckStudio
saveFileDialog.DefaultExt = ".3dst";
if (saveFileDialog.ShowDialog() == DialogResult.OK)
{
using (var fs = saveFileDialog.OpenFile())
using (var ms = new MemoryStream(file.Data))
{
using var ms = new MemoryStream(file.Data);
Image img = Image.FromStream(ms);
_3DSUtil.SetImageTo3DST(fs, img);
var writer = new _3DSTextureWriter(img);
writer.WriteToFile(saveFileDialog.FileName);
}
}
}

View File

@@ -176,7 +176,8 @@
<Compile Include="Classes\FileTypes\CSMBFile.cs" />
<Compile Include="Classes\FileTypes\PCKAudioFile.cs" />
<Compile Include="Classes\FileTypes\Binka.cs" />
<Compile Include="Classes\FileTypes\CSM.cs" />
<Compile Include="Classes\IO\3DST\3DSTextureReader.cs" />
<Compile Include="Classes\IO\3DST\3DSTextureWriter.cs" />
<Compile Include="Classes\IO\CSMB\CSMBFileReader.cs" />
<Compile Include="Classes\IO\CSMB\CSMBFileWriter.cs" />
<Compile Include="Classes\IO\PCK\PCKAudioFileReader.cs" />
@@ -185,7 +186,6 @@
<Compile Include="Classes\IO\Sounds\Sounds.cs" />
<Compile Include="Classes\Misc\FTPClient.cs" />
<Compile Include="Classes\Models\DefaultModels\Steve64x64Model.cs" />
<Compile Include="Classes\Utils\3DS\3DSUtil.cs" />
<Compile Include="Classes\Utils\ARC\ARCUtil.cs" />
<Compile Include="Classes\Extensions\ImageExtensions.cs" />
<Compile Include="Classes\Utils\SkinANIM.cs" />
@@ -464,7 +464,7 @@
<DependentUpon>CreditsForm.cs</DependentUpon>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Classes\Utils\3DS\TextureCodec.cs" />
<Compile Include="Classes\IO\3DST\TextureCodec.cs" />
<EmbeddedResource Include="Forms\Additional-Popups\EntityForms\AddEntry.resx">
<DependentUpon>AddEntry.cs</DependentUpon>
</EmbeddedResource>