Tons of stuff!

- Compress BC1 with alpha.
- Add GFPAK rebuilding.
- Fix some lag issues with bntx textures loading
- Fix saving multiple files.
- Support DDS cubemap importing
- Support rigged DAE/FBX files.
- Support animation playing thanks to smash forge.
- Some minor stuff to prepare custom animations.
- Many bug fixes.
This commit is contained in:
KillzXGaming 2018-11-22 10:20:12 -05:00
parent 029f350526
commit 50ea4183ef
84 changed files with 26073 additions and 496 deletions

22
.gitignore vendored
View file

@ -1,27 +1,5 @@
.vs/Switch_Toolbox/v15/Server/sqlite3/db.lock .vs/Switch_Toolbox/v15/Server/sqlite3/db.lock
*.suo
*.user
*.userosscache
*.sln.docstates
*.resources *.resources
Debug/ Debug/
Release/ Release/
.vs/Switch_Toolbox/v15/.suo
.vs/Switch_Toolbox/v15/Server/sqlite3/storage.ide
.vs/Switch_Toolbox/v15/Server/sqlite3/storage.ide-shm
.vs/Switch_Toolbox/v15/Server/sqlite3/storage.ide-wal
.vs/Switch_Toolbox/v15/Server/sqlite3/storage.ide-wal
.vs/Switch_Toolbox/v15/Server/sqlite3/storage.ide-shm
.vs/Switch_Toolbox/v15/Server/sqlite3/storage.ide
.vs/Switch_Toolbox/v15/.suo
.vs/Switch_Toolbox/v15/Server/sqlite3/storage.ide-wal
.vs/Switch_Toolbox/v15/Server/sqlite3/storage.ide-shm
.vs/Switch_Toolbox/v15/Server/sqlite3/storage.ide
.vs/Switch_Toolbox/v15/.suo
*.ide
.vs/Switch_Toolbox/v15/Server/sqlite3/storage.ide-wal
.vs/Switch_Toolbox/v15/Server/sqlite3/storage.ide-shm
.vs/Switch_Toolbox/v15/Server/sqlite3/storage.ide
.vs/Switch_Toolbox/v15/.suo
.vs/Switch_Toolbox/v15/.suo

Binary file not shown.

View file

@ -46,7 +46,7 @@ namespace FirstPlugin
this.eitorRoot = value; this.eitorRoot = value;
} }
} }
private void SaveFile() public void SaveFile()
{ {
List<IFileFormat> formats = new List<IFileFormat>(); List<IFileFormat> formats = new List<IFileFormat>();
formats.Add(this); formats.Add(this);
@ -112,7 +112,6 @@ namespace FirstPlugin
bfres = new BFRESRender(); bfres = new BFRESRender();
bfres.ResFileNode = new ResourceFile(this); bfres.ResFileNode = new ResourceFile(this);
bfres.ResFileNode.BFRESRender = bfres; bfres.ResFileNode.BFRESRender = bfres;
bfres.SaveFile = SaveFile;
EditorRoot = bfres.ResFileNode; EditorRoot = bfres.ResFileNode;

View file

@ -193,8 +193,12 @@ namespace Bfres.Structs
string Magic = f.ReadMagic(0, 4); string Magic = f.ReadMagic(0, 4);
if (Magic == "BNTX") if (Magic == "BNTX")
{ {
BinaryTextureContainer bntxTreeNode = new BinaryTextureContainer(extfile.Data, Name, resFile.Name); BNTX bntx = new BNTX();
Nodes["EXT"].Nodes.Add(bntxTreeNode); bntx.Data = extfile.Data;
bntx.FileName = Name;
bntx.Load();
bntx.IFileInfo.InArchive = true;
Nodes["EXT"].Nodes.Add(bntx.EditorRoot);
} }
else if (Magic == "FSHA") else if (Magic == "FSHA")
{ {
@ -232,7 +236,7 @@ namespace Bfres.Structs
} }
private void Save(object sender, EventArgs args) private void Save(object sender, EventArgs args)
{ {
BFRESRender.SaveFile(); ((BFRES)FileHandler).SaveFile();
} }
private void Rename(object sender, EventArgs args) private void Rename(object sender, EventArgs args)
{ {
@ -292,7 +296,7 @@ namespace Bfres.Structs
Nodes.Add(FSKA); Nodes.Add(FSKA);
} }
} }
public class FskaFolder : TreeNodeCustom public class FskaFolder : AnimationGroupNode
{ {
public FskaFolder() public FskaFolder()
{ {
@ -319,10 +323,10 @@ namespace Bfres.Structs
Nodes.Add(skeletonAnim); Nodes.Add(skeletonAnim);
} }
} }
public override void OnClick(TreeView treeView) /* public override void OnClick(TreeView treeView)
{ {
FormLoader.LoadEditor(this, Text); FormLoader.LoadEditor(this, Text);
} }*/
} }
public class FmdlFolder : TreeNodeCustom public class FmdlFolder : TreeNodeCustom
{ {
@ -631,36 +635,34 @@ namespace Bfres.Structs
bone.Text = bonean.Text; bone.Text = bonean.Text;
for (int Frame = 0; Frame < ska.FrameCount; Frame++) for (int Frame = 0; Frame < ska.FrameCount; Frame++)
{ {
//Set base/start values for bones.
//Note. BOTW doesn't use base values as it uses havok engine. Need to add option to disable these
if (Frame == 0) if (Frame == 0)
{ {
if (bn.FlagsBase.HasFlag(BoneAnimFlagsBase.Scale)) if (bn.FlagsBase.HasFlag(BoneAnimFlagsBase.Scale))
{ {
bone.XSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.sca.X }); bone.XSCA.Keys.Add(new KeyFrame() { Frame = 0, Value = bonean.sca.X });
bone.YSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.sca.Y }); bone.YSCA.Keys.Add(new KeyFrame() { Frame = 0, Value = bonean.sca.Y });
bone.ZSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.sca.Z }); bone.ZSCA.Keys.Add(new KeyFrame() { Frame = 0, Value = bonean.sca.Z });
} }
if (bn.FlagsBase.HasFlag(BoneAnimFlagsBase.Rotate)) if (bn.FlagsBase.HasFlag(BoneAnimFlagsBase.Rotate))
{ {
bone.XROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.rot.X }); bone.XROT.Keys.Add(new KeyFrame() { Frame = 0, Value = bonean.rot.X });
bone.YROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.rot.Y }); bone.YROT.Keys.Add(new KeyFrame() { Frame = 0, Value = bonean.rot.Y });
bone.ZROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.rot.Z }); bone.ZROT.Keys.Add(new KeyFrame() { Frame = 0, Value = bonean.rot.Z });
bone.WROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.rot.W }); bone.WROT.Keys.Add(new KeyFrame() { Frame = 0, Value = bonean.rot.W });
} }
if (bn.FlagsBase.HasFlag(BoneAnimFlagsBase.Translate)) if (bn.FlagsBase.HasFlag(BoneAnimFlagsBase.Translate))
{ {
bone.XPOS.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.pos.X }); bone.XPOS.Keys.Add(new KeyFrame() { Frame = 0, Value = bonean.pos.X });
bone.YPOS.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.pos.Y }); bone.YPOS.Keys.Add(new KeyFrame() { Frame = 0, Value = bonean.pos.Y });
bone.ZPOS.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.pos.Z }); bone.ZPOS.Keys.Add(new KeyFrame() { Frame = 0, Value = bonean.pos.Z });
} }
} }
foreach (FSKATrack track in bonean.tracks) foreach (FSKATrack track in bonean.tracks)
{ {
Animation.KeyFrame frame = new Animation.KeyFrame(); KeyFrame frame = new KeyFrame();
frame.InterType = Animation.InterpolationType.HERMITE; frame.InterType = Animation.InterpolationType.HERMITE;
frame.Frame = Frame; frame.Frame = Frame;
@ -668,8 +670,6 @@ namespace Bfres.Structs
FSKAKey right = track.GetRight(Frame); FSKAKey right = track.GetRight(Frame);
float value; float value;
value = Animation.Hermite(Frame, left.frame, right.frame, 0, 0, left.unk1, right.unk1); value = Animation.Hermite(Frame, left.frame, right.frame, 0, 0, left.unk1, right.unk1);
// interpolate the value and apply // interpolate the value and apply
@ -711,12 +711,9 @@ namespace Bfres.Structs
{ {
Text = b.Name; Text = b.Name;
if (b.BaseData.Scale != Syroot.Maths.Vector3F.Zero) sca = new Vector3(b.BaseData.Scale.X, b.BaseData.Scale.Y, b.BaseData.Scale.Z);
sca = new Vector3(b.BaseData.Scale.X, b.BaseData.Scale.Y, b.BaseData.Scale.Z); rot = new Vector4(b.BaseData.Rotate.X, b.BaseData.Rotate.Y, b.BaseData.Rotate.Z, b.BaseData.Rotate.W);
if (b.BaseData.Rotate != Syroot.Maths.Vector4F.Zero) pos = new Vector3(b.BaseData.Translate.X, b.BaseData.Translate.Y, b.BaseData.Translate.Z);
rot = new Vector4(b.BaseData.Rotate.X, b.BaseData.Rotate.Y, b.BaseData.Rotate.Z, b.BaseData.Rotate.W);
if (b.BaseData.Translate != Syroot.Maths.Vector3F.Zero)
pos = new Vector3(b.BaseData.Translate.X, b.BaseData.Translate.Y, b.BaseData.Translate.Z);
foreach (AnimCurve tr in b.Curves) foreach (AnimCurve tr in b.Curves)
{ {

View file

@ -303,6 +303,157 @@ namespace FirstPlugin
VertexBufferHelperAttrib attd = helper[attName]; VertexBufferHelperAttrib attd = helper[attName];
return attd.Data; return attd.Data;
} }
public static SkeletalAnim SetSkeletalAniamtion(BfresSkeletonAnim anim)
{
SkeletalAnim animation = new SkeletalAnim();
animation.Name = anim.Text;
animation.FrameCount = anim.FrameCount;
animation.FlagsAnimSettings = SkeletalAnimFlags.Looping;
animation.FlagsRotate = SkeletalAnimFlagsRotate.EulerXYZ;
animation.FlagsScale = SkeletalAnimFlagsScale.Maya;
animation.BindIndices = new ushort[anim.Bones.Count];
animation.BindSkeleton = new Skeleton();
animation.BakedSize = 0;
animation.BoneAnims = new List<BoneAnim>();
animation.UserDataDict = new ResDict();
animation.UserDatas = new List<UserData>();
foreach (var bone in anim.Bones)
animation.BoneAnims.Add(createBoneAnim(bone, anim));
return animation;
}
private static BoneAnim createBoneAnim(Animation.KeyNode bone, BfresSkeletonAnim anim)
{
BoneAnim boneAnim = new BoneAnim();
boneAnim.Name = bone.Name;
var posx = bone.XPOS.GetValue(0);
var posy = bone.YPOS.GetValue(0);
var posz = bone.ZPOS.GetValue(0);
var scax = bone.XSCA.GetValue(0);
var scay = bone.YSCA.GetValue(0);
var scaz = bone.ZSCA.GetValue(0);
var rotx = bone.XROT.GetValue(0);
var roty = bone.YROT.GetValue(0);
var rotz = bone.ZROT.GetValue(0);
var rotw = bone.WROT.GetValue(0);
BoneAnimData boneBaseData = new BoneAnimData();
boneBaseData.Translate = new Syroot.Maths.Vector3F(posx, posy, posz);
boneBaseData.Scale = new Syroot.Maths.Vector3F(scax, scay, scaz);
boneBaseData.Rotate = new Syroot.Maths.Vector4F(rotx, roty, rotz, rotw);
boneAnim.BaseData = boneBaseData;
boneAnim.BeginBaseTranslate = 0;
boneAnim.BeginRotate = 0;
boneAnim.BeginTranslate = 0;
boneAnim.Curves = new List<AnimCurve>();
boneAnim.FlagsBase = BoneAnimFlagsBase.Translate | BoneAnimFlagsBase.Scale | BoneAnimFlagsBase.Rotate;
boneAnim.FlagsTransform = BoneAnimFlagsTransform.Identity;
if (bone.XPOS.HasAnimation())
{
boneAnim.FlagsCurve |= BoneAnimFlagsCurve.TranslateX;
boneAnim.Curves.Add(SetAnimationCurve(bone.XPOS));
}
if (bone.YPOS.HasAnimation())
{
boneAnim.FlagsCurve |= BoneAnimFlagsCurve.TranslateY;
boneAnim.Curves.Add(SetAnimationCurve(bone.YPOS));
}
if (bone.ZPOS.HasAnimation())
{
boneAnim.FlagsCurve |= BoneAnimFlagsCurve.TranslateZ;
boneAnim.Curves.Add(SetAnimationCurve(bone.ZPOS));
}
if (bone.XSCA.HasAnimation())
{
boneAnim.FlagsCurve |= BoneAnimFlagsCurve.ScaleX;
boneAnim.Curves.Add(SetAnimationCurve(bone.XSCA));
}
if (bone.YSCA.HasAnimation())
{
boneAnim.FlagsCurve |= BoneAnimFlagsCurve.ScaleY;
boneAnim.Curves.Add(SetAnimationCurve(bone.YSCA));
}
if (bone.ZSCA.HasAnimation())
{
boneAnim.FlagsCurve |= BoneAnimFlagsCurve.ScaleZ;
boneAnim.Curves.Add(SetAnimationCurve(bone.ZSCA));
}
if (bone.XROT.HasAnimation())
{
boneAnim.FlagsCurve |= BoneAnimFlagsCurve.RotateX;
boneAnim.Curves.Add(SetAnimationCurve(bone.XROT));
}
if (bone.YROT.HasAnimation())
{
boneAnim.FlagsCurve |= BoneAnimFlagsCurve.RotateY;
boneAnim.Curves.Add(SetAnimationCurve(bone.YROT));
}
if (bone.ZROT.HasAnimation())
{
boneAnim.FlagsCurve |= BoneAnimFlagsCurve.RotateZ;
boneAnim.Curves.Add(SetAnimationCurve(bone.ZROT));
}
if (bone.WROT.HasAnimation())
{
boneAnim.FlagsCurve |= BoneAnimFlagsCurve.RotateW;
boneAnim.Curves.Add(SetAnimationCurve(bone.WROT));
}
return boneAnim;
}
private static AnimCurve SetAnimationCurve(Animation.KeyGroup keyGroup)
{
AnimCurve curve = new AnimCurve();
curve.Frames = new float[(int)keyGroup.Keys.Count];
curve.FrameType = AnimCurveFrameType.Single;
curve.KeyType = AnimCurveKeyType.Single;
curve.EndFrame = keyGroup.FrameCount;
curve.AnimDataOffset = 0;
curve.Delta = 0;
curve.Scale = 1;
curve.StartFrame = 0;
curve.Offset = 0;
var frame = keyGroup.GetKeyFrame(0);
int valuesLength = 1;
if (frame.InterType == Animation.InterpolationType.HERMITE)
{
curve.CurveType = AnimCurveType.Cubic;
curve.Keys = new float[keyGroup.Keys.Count, 4];
for (int k = 0; k < keyGroup.Keys.Count; k++)
{
float value = keyGroup.GetValue(keyGroup.Keys[k].Frame);
curve.Keys[k, 0] = value;
curve.Keys[k, 1] = 0;
curve.Keys[k, 2] = 0;
curve.Keys[k, 3] = 0;
curve.Frames[k] = keyGroup.Keys[k].Frame;
}
}
if (frame.InterType == Animation.InterpolationType.LINEAR)
{
curve.CurveType = AnimCurveType.Linear;
curve.Keys = new float[keyGroup.Keys.Count, 2];
}
if (frame.InterType == Animation.InterpolationType.STEP)
{
curve.CurveType = AnimCurveType.StepInt;
curve.Keys = new float[keyGroup.Keys.Count, 1];
}
if (frame.InterType == Animation.InterpolationType.STEPBOOL)
{
curve.CurveType = AnimCurveType.StepBool;
curve.Keys = new float[keyGroup.Keys.Count, 1];
}
return curve;
}
public static void SetSkeleton(this TreeNodeCustom skl, Skeleton skeleton, FSKL RenderableSkeleton) public static void SetSkeleton(this TreeNodeCustom skl, Skeleton skeleton, FSKL RenderableSkeleton)
{ {
@ -327,9 +478,9 @@ namespace FirstPlugin
RenderableSkeleton.update(); RenderableSkeleton.update();
RenderableSkeleton.reset(); RenderableSkeleton.reset();
foreach (var bone in RenderableSkeleton.bones) // foreach (var bone in RenderableSkeleton.bones)
if (bone.Parent == null) // if (bone.Parent == null)
skl.Nodes.Add(bone); // skl.Nodes.Add(bone);
Runtime.abstractGlDrawables.Add(RenderableSkeleton); Runtime.abstractGlDrawables.Add(RenderableSkeleton);
} }

View file

@ -40,10 +40,10 @@ namespace FirstPlugin
public void Load() public void Load()
{ {
IsActive = true; IsActive = true;
EditorRoot = new TreeNodeFile(FileName, this); EditorRoot = new GFLXPACK(FileName, this);
IFileInfo = new IFileInfo();
GFLXPACK gflx = new GFLXPACK(); ((GFLXPACK)EditorRoot).Read(new FileReader(new MemoryStream(Data)), EditorRoot);
gflx.Read(new FileReader(new MemoryStream(Data)), EditorRoot);
} }
public void Unload() public void Unload()
@ -52,19 +52,107 @@ namespace FirstPlugin
} }
public byte[] Save() public byte[] Save()
{ {
return null; MemoryStream mem = new MemoryStream();
((GFLXPACK)EditorRoot).Write(new FileWriter(mem));
return mem.ToArray();
} }
} }
public class GFLXPACK
public class GFLXPACK : TreeNodeFile
{ {
public GFLXPACK(string text, IFileFormat format)
{
Text = text;
FileHandler = format;
ContextMenu = new ContextMenu();
MenuItem save = new MenuItem("Save");
ContextMenu.MenuItems.Add(save);
save.Click += Save;
MenuItem previewFiles = new MenuItem("Preview Window");
ContextMenu.MenuItems.Add(previewFiles);
previewFiles.Click += PreviewWindow;
}
private void Save(object sender, EventArgs args)
{
List<IFileFormat> formats = new List<IFileFormat>();
formats.Add(FileHandler);
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = Utils.GetAllFilters(formats);
sfd.FileName = FileHandler.FileName;
if (sfd.ShowDialog() == DialogResult.OK)
{
Cursor.Current = Cursors.WaitCursor;
SaveCompressFile(FileHandler.Save(), sfd.FileName, FileHandler.IFileInfo.Alignment);
}
}
private void SaveCompressFile(byte[] data, string FileName, int Alignment = 0, bool EnableDialog = true)
{
if (EnableDialog)
{
DialogResult save = MessageBox.Show("Compress file?", "File Save", MessageBoxButtons.YesNo);
if (save == DialogResult.Yes)
data = EveryFileExplorer.YAZ0.Compress(data, 3, (uint)Alignment);
}
File.WriteAllBytes(FileName, data);
MessageBox.Show($"File has been saved to {FileName}");
Cursor.Current = Cursors.Default;
}
private void PreviewWindow(object sender, EventArgs args)
{
PreviewFormatList previewFormatList = new PreviewFormatList();
if (previewFormatList.ShowDialog() == DialogResult.OK)
{
CallRecursive(TreeView);
PreviewEditor previewWindow = new PreviewEditor();
previewWindow.Show();
}
}
private void CallRecursive(TreeView treeView)
{
// Print each node recursively.
TreeNodeCollection nodes = treeView.Nodes;
foreach (TreeNode n in nodes)
{
PrintRecursive(n);
}
}
private void PrintRecursive(TreeNode treeNode)
{
if (treeNode is FileEntry)
{
FileEntry file = (FileEntry)treeNode;
if (file.ImageKey == "bntx")
OpenFile(file.Name, file.data, file);
if (file.ImageKey == "bntx")
Console.WriteLine(file.Name);
// if (file.ImageKey == "bfres")
// OpenFile(file.Name, GetASSTData(file.FullName), TreeView);
}
// Print each node recursively.
foreach (TreeNode tn in treeNode.Nodes)
{
PrintRecursive(tn);
}
}
public ushort BOM; public ushort BOM;
public uint Version; public uint Version;
public List<FileEntry> files = new List<FileEntry>(); public List<FileEntry> files = new List<FileEntry>();
public List<UInt64> hashes = new List<UInt64>(); public List<UInt64> hashes = new List<UInt64>();
public List<HashIndex> hashIndices = new List<HashIndex>();
public int version;
public int FolderCount;
public void Read(FileReader reader, TreeNode root) public void Read(FileReader reader, TreeNode root)
{ {
@ -72,15 +160,13 @@ namespace FirstPlugin
if (Signature != "GFLXPACK") if (Signature != "GFLXPACK")
throw new Exception($"Invalid signature {Signature}! Expected GFLXPACK."); throw new Exception($"Invalid signature {Signature}! Expected GFLXPACK.");
uint unk = reader.ReadUInt32(); version = reader.ReadInt32();
uint padding = reader.ReadUInt32(); uint padding = reader.ReadUInt32();
uint FileCount = reader.ReadUInt32(); uint FileCount = reader.ReadUInt32();
uint unk2 = reader.ReadUInt32(); FolderCount = reader.ReadInt32();
ulong FileInfoOffset = reader.ReadUInt64(); ulong FileInfoOffset = reader.ReadUInt64();
ulong hashArrayOffset = reader.ReadUInt64(); ulong hashArrayOffset = reader.ReadUInt64();
ulong UnkOffset = reader.ReadUInt64(); ulong hashArrayIndexOffset = reader.ReadUInt64();
ulong Unk2Offset = reader.ReadUInt64();
ulong Unk3Offset = reader.ReadUInt64();
reader.Seek((long)hashArrayOffset, SeekOrigin.Begin); reader.Seek((long)hashArrayOffset, SeekOrigin.Begin);
for (int i = 0; i < FileCount; i++) for (int i = 0; i < FileCount; i++)
@ -88,6 +174,13 @@ namespace FirstPlugin
ulong hash = reader.ReadUInt64(); ulong hash = reader.ReadUInt64();
hashes.Add(hash); hashes.Add(hash);
} }
reader.Seek((long)hashArrayIndexOffset, SeekOrigin.Begin);
for (int i = 0; i < FileCount; i++)
{
HashIndex hashindex = new HashIndex();
hashindex.Read(reader);
hashIndices.Add(hashindex);
}
reader.Seek((long)FileInfoOffset, SeekOrigin.Begin); reader.Seek((long)FileInfoOffset, SeekOrigin.Begin);
for (int i = 0; i < FileCount; i++) for (int i = 0; i < FileCount; i++)
@ -95,12 +188,60 @@ namespace FirstPlugin
FileEntry fileEntry = new FileEntry(); FileEntry fileEntry = new FileEntry();
fileEntry.Read(reader); fileEntry.Read(reader);
fileEntry.Text = hashes[i].ToString(); fileEntry.Text = hashes[i].ToString();
files.Add(fileEntry);
root.Nodes.Add(fileEntry); root.Nodes.Add(fileEntry);
files.Add(fileEntry);
} }
} }
public void Write(FileWriter writer)
{
writer.WriteSignature("GFLXPACK");
writer.Write(version);
writer.Write(0);
writer.Write(files.Count);
writer.Write(FolderCount);
long FileInfoOffset = writer.Position;
writer.Write(0L);
long HashArrayOffset = writer.Position;
writer.Write(0L);
long HashIndexArrOffset = writer.Position;
writer.Write(0L);
//Now write all sections
writer.WriteUint64Offset(HashArrayOffset);
writer.Write(hashes);
writer.WriteUint64Offset(HashIndexArrOffset);
foreach (var hashIndx in hashIndices)
hashIndx.Write(writer);
writer.WriteUint64Offset(FileInfoOffset);
foreach (var fileTbl in files)
fileTbl.Write(writer);
//Save data blocks
foreach (var fileTbl in files)
{
fileTbl.WriteBlock(writer);
}
}
public class HashIndex
{
public ulong hash;
public int Index;
public uint unkown;
public void Read(FileReader reader)
{
hash = reader.ReadUInt64();
Index = reader.ReadInt32();
unkown = reader.ReadUInt32(); //Always 0xCC?
}
public void Write(FileWriter writer)
{
writer.Write(hash);
writer.Write(Index);
writer.Write(unkown);
}
}
public class FileEntry : TreeNodeCustom public class FileEntry : TreeNodeCustom
{ {
public FileEntry() public FileEntry()
@ -114,21 +255,26 @@ namespace FirstPlugin
export.Click += Export; export.Click += Export;
} }
public uint unkown;
public uint CompressionType;
public byte[] data; public byte[] data;
private long DataOffset;
private byte[] CompressedData;
public IFileFormat FileHandler;
public void Read(FileReader reader) public void Read(FileReader reader)
{ {
uint unk = reader.ReadUInt16(); unkown = reader.ReadUInt16(); //Usually 9?
uint unk2 = reader.ReadUInt16(); CompressionType = reader.ReadUInt16();
uint unk3 = reader.ReadUInt32(); uint DecompressedFileSize = reader.ReadUInt32();
uint FileSize = reader.ReadUInt32(); uint CompressedFileSize = reader.ReadUInt32();
uint unk4 = reader.ReadUInt32(); uint padding = reader.ReadUInt32();
ulong FileOffset = reader.ReadUInt64(); ulong FileOffset = reader.ReadUInt64();
using (reader.TemporarySeek((long)FileOffset, SeekOrigin.Begin)) using (reader.TemporarySeek((long)FileOffset, SeekOrigin.Begin))
{ {
byte type = reader.ReadByte(); data = reader.ReadBytes((int)CompressedFileSize);
data = reader.ReadBytes((int)FileSize - 1); data = STLibraryCompression.Type_LZ4.Decompress(data, 0, (int)CompressedFileSize, (int)DecompressedFileSize);
string ext = SARCExt.SARC.GuessFileExtension(data); string ext = SARCExt.SARC.GuessFileExtension(data);
@ -153,11 +299,45 @@ namespace FirstPlugin
} }
} }
} }
public void Write(FileWriter writer)
{
if (FileHandler != null && FileHandler.CanSave)
{
data = FileHandler.Save();
}
CompressedData = Compress(data, CompressionType);
writer.Write((ushort)unkown);
writer.Write((ushort)CompressionType);
writer.Write(data.Length);
writer.Write(CompressedData.Length);
writer.Write(0);
DataOffset = writer.Position;
writer.Write(0L);
}
public void WriteBlock(FileWriter writer)
{
writer.WriteUint64Offset(DataOffset);
writer.Write(CompressedData);
}
public static byte[] Compress(byte[] data, uint Type)
{
if (Type == 2)
{
return STLibraryCompression.Type_LZ4.Compress(data);
}
else
throw new Exception("Unkown compression type?");
}
public override void OnClick(TreeView treeview) public override void OnClick(TreeView treeview)
{ {
} }
public override void OnMouseLeftClick(TreeView treeView)
{
ReplaceNode(this.Parent, this, OpenFile(Name, data, this));
}
private void Export(object sender, EventArgs args) private void Export(object sender, EventArgs args)
{ {
SaveFileDialog sfd = new SaveFileDialog(); SaveFileDialog sfd = new SaveFileDialog();
@ -166,11 +346,87 @@ namespace FirstPlugin
if (sfd.ShowDialog() == DialogResult.OK) if (sfd.ShowDialog() == DialogResult.OK)
{ {
File.WriteAllBytes(sfd.FileName, STLibraryCompression.Type_LZ4.Decompress(data)); File.WriteAllBytes(sfd.FileName, data);
} }
} }
} }
public static TreeNode OpenFile(string FileName, byte[] data, FileEntry fileEntry, bool Compressed = false, CompressionType CompType = 0)
{
Cursor.Current = Cursors.WaitCursor;
FileReader fileReader = new FileReader(data);
string Magic4 = fileReader.ReadMagic(0, 4);
string Magic2 = fileReader.ReadMagic(0, 2);
if (Magic4 == "Yaz0")
{
data = EveryFileExplorer.YAZ0.Decompress(data);
return OpenFile(FileName, data, fileEntry, true, (CompressionType)1);
}
if (Magic4 == "ZLIB")
{
data = FileReader.InflateZLIB(fileReader.getSection(64, data.Length - 64));
return OpenFile(FileName, data, fileEntry, true, (CompressionType)2);
}
fileReader.Dispose();
fileReader.Close();
foreach (IFileFormat fileFormat in FileManager.GetFileFormats())
{
if (fileFormat.Magic == Magic4 || fileFormat.Magic == Magic2)
{
fileFormat.CompressionType = CompType;
fileFormat.FileIsCompressed = Compressed;
fileFormat.Data = data;
fileFormat.Load();
fileFormat.FileName = Path.GetFileName(FileName);
fileFormat.FilePath = FileName;
fileFormat.IFileInfo = new IFileInfo();
fileFormat.IFileInfo.InArchive = true;
if (fileFormat.EditorRoot == null)
return null;
fileFormat.EditorRoot.ImageKey = fileEntry.ImageKey;
fileFormat.EditorRoot.SelectedImageKey = fileEntry.SelectedImageKey;
fileFormat.EditorRoot.Text = fileEntry.Text;
fileEntry.FileHandler = fileFormat;
return fileFormat.EditorRoot;
}
if (fileFormat.Magic == string.Empty)
{
foreach (string str3 in fileFormat.Extension)
{
if (str3.Remove(0, 1) == Path.GetExtension(FileName))
{
fileFormat.Data = data;
fileFormat.Load();
fileFormat.FileName = Path.GetFileName(FileName);
fileFormat.FilePath = FileName;
fileFormat.IFileInfo = new IFileInfo();
fileFormat.IFileInfo.InArchive = true;
if (fileFormat.EditorRoot == null)
return null;
fileFormat.EditorRoot.ImageKey = fileEntry.ImageKey;
fileFormat.EditorRoot.SelectedImageKey = fileEntry.SelectedImageKey;
fileFormat.EditorRoot.Text = fileEntry.Text;
fileEntry.FileHandler = fileFormat;
return fileFormat.EditorRoot;
}
}
}
}
return (TreeNode)null;
}
public static void ReplaceNode(TreeNode node, TreeNode replaceNode, TreeNode NewNode)
{
if (NewNode == null)
return;
int index = node.Nodes.IndexOf(replaceNode);
node.Nodes.RemoveAt(index);
node.Nodes.Insert(index, NewNode);
}
} }
public class FileUnk public class FileUnk
{ {
public uint Size; public uint Size;

View file

@ -46,11 +46,10 @@ namespace FirstPlugin
UseEditMenu = true; UseEditMenu = true;
var SzsFiles = SARCExt.SARC.UnpackRamN(Data); var SzsFiles = SARCExt.SARC.UnpackRamN(Data);
sarcData = new SarcData(); sarcData = new SarcData();
sarcData.HashOnly = false; sarcData.HashOnly = false;
sarcData.Files = SzsFiles.Files; sarcData.Files = SzsFiles.Files;
sarcData.endianness = Syroot.BinaryData.ByteOrder.LittleEndian; sarcData.endianness = GetByteOrder(Data);
SarcHash = Utils.GenerateUniqueHashID(); SarcHash = Utils.GenerateUniqueHashID();
IFileInfo = new IFileInfo(); IFileInfo = new IFileInfo();
@ -59,6 +58,22 @@ namespace FirstPlugin
sarcData.Files.Clear(); sarcData.Files.Clear();
} }
public Syroot.BinaryData.ByteOrder GetByteOrder(byte[] data)
{
using (FileReader reader = new FileReader(data))
{
reader.ByteOrder = Syroot.BinaryData.ByteOrder.BigEndian;
reader.Seek(6);
ushort bom = reader.ReadUInt16();
reader.Close();
reader.Dispose();
if (bom == 0xFFFE)
return Syroot.BinaryData.ByteOrder.LittleEndian;
else
return Syroot.BinaryData.ByteOrder.BigEndian;
}
}
public void Unload() public void Unload()
{ {
@ -248,7 +263,7 @@ namespace FirstPlugin
public override void OnClick(TreeView treeView) public override void OnClick(TreeView treeView)
{ {
} }
public override void OnMouseClick(TreeView treeView) public override void OnMouseLeftClick(TreeView treeView)
{ {
ReplaceNode(this.Parent, this, OpenFile(Name, Data, this)); ReplaceNode(this.Parent, this, OpenFile(Name, Data, this));
} }

View file

@ -161,10 +161,11 @@ namespace FirstPlugin
public void Load() public void Load()
{ {
IFileInfo = new IFileInfo();
IsActive = true; IsActive = true;
UseEditMenu = true; UseEditMenu = true;
CanSave = true; CanSave = true;
bntx = new BinaryTextureContainer(Data, FileName, "", this); bntx = new BinaryTextureContainer(Data, FileName, "", this);
EditorRoot = bntx; EditorRoot = bntx;
} }
@ -194,12 +195,41 @@ namespace FirstPlugin
public BntxFile BinaryTexFile; public BntxFile BinaryTexFile;
public string FileNameText; public string FileNameText;
MenuItem save = new MenuItem("Save");
MenuItem replace = new MenuItem("Replace");
MenuItem rename = new MenuItem("Rename");
MenuItem importTex = new MenuItem("Import Texture");
MenuItem exportAll = new MenuItem("Export All Textures");
MenuItem clear = new MenuItem("Clear");
private bool hasParent;
public bool HasParent
{
get
{
hasParent = Parent != null;
replace.Enabled = hasParent;
rename.Enabled = hasParent;
return hasParent;
}
}
public bool CanReplace;
public bool AllGLInitialized
{
get
{
if (Textures.Any(item => item.Value.GLInitialized == false))
return false;
else
return true;
}
}
public BinaryTextureContainer() public BinaryTextureContainer()
{ {
ImageKey = "bntx"; ImageKey = "bntx";
SelectedImageKey = "bntx"; SelectedImageKey = "bntx";
} }
public BinaryTextureContainer(byte[] data, string Name = "", string FileName = "", IFileFormat handler = null) public BinaryTextureContainer(byte[] data, string Name = "", string FileName = "", IFileFormat handler = null)
{ {
if (data.Length == 0) if (data.Length == 0)
@ -212,6 +242,25 @@ namespace FirstPlugin
LoadFile(data, Name); LoadFile(data, Name);
PluginRuntime.bntxContainers.Add(this); PluginRuntime.bntxContainers.Add(this);
FileHandler = handler;
//Check if bntx is parented to determine if an archive is used
bool checkParent = HasParent;
ContextMenu = new ContextMenu();
ContextMenu.MenuItems.Add(save);
ContextMenu.MenuItems.Add(replace);
ContextMenu.MenuItems.Add(rename);
ContextMenu.MenuItems.Add(importTex);
ContextMenu.MenuItems.Add(exportAll);
ContextMenu.MenuItems.Add(clear);
save.Click += Save;
replace.Click += Import;
rename.Click += Rename;
importTex.Click += ImportTexture;
exportAll.Click += ExportAll;
clear.Click += Clear;
} }
private byte[] CreateNewBNTX(string Name) private byte[] CreateNewBNTX(string Name)
{ {
@ -242,14 +291,12 @@ namespace FirstPlugin
} }
public override void OnClick(TreeView treeView) public override void OnClick(TreeView treeView)
{ {
Console.WriteLine(FirstPlugin.MainF);
foreach (Control control in FirstPlugin.MainF.Controls)
{
if (control is DockPanel)
{
} }
} //Check right click to enable/disable certain context menus
public override void OnMouseRightClick(TreeView treeview)
{
bool checkParent = HasParent;
} }
public void LoadFile(byte[] data, string Name = "") public void LoadFile(byte[] data, string Name = "")
@ -276,23 +323,8 @@ namespace FirstPlugin
Nodes.Add(texData); Nodes.Add(texData);
Textures.Add(tex.Name, texData); Textures.Add(tex.Name, texData);
} }
BinaryTexFile.Textures.Clear(); //We don't need these in memeory anymore
ContextMenu = new ContextMenu(); BinaryTexFile.TextureDict.Clear();
MenuItem export = new MenuItem("Export BNTX");
ContextMenu.MenuItems.Add(export);
export.Click += Export;
MenuItem replace = new MenuItem("Replace BNTX");
ContextMenu.MenuItems.Add(replace);
replace.Click += Import;
MenuItem importTex = new MenuItem("Import Texture");
ContextMenu.MenuItems.Add(importTex);
importTex.Click += ImportTexture;
MenuItem exportAll = new MenuItem("Export All Textures");
ContextMenu.MenuItems.Add(exportAll);
exportAll.Click += ExportAll;
MenuItem clear = new MenuItem("Clear");
ContextMenu.MenuItems.Add(clear);
clear.Click += Clear;
} }
private void ImportTexture(object sender, EventArgs args) private void ImportTexture(object sender, EventArgs args)
{ {
@ -341,8 +373,15 @@ namespace FirstPlugin
importer.LoadSettings(settings, this); importer.LoadSettings(settings, this);
if (importer.ShowDialog() == DialogResult.OK) if (importer.ShowDialog() == DialogResult.OK)
{ {
Cursor.Current = Cursors.WaitCursor;
foreach (var setting in settings) foreach (var setting in settings)
{ {
if (setting.GenerateMipmaps)
{
setting.DataBlockOutput.Clear();
setting.DataBlockOutput.Add(setting.GenerateMips());
}
if (setting.DataBlockOutput != null) if (setting.DataBlockOutput != null)
{ {
Texture tex = setting.FromBitMap(setting.DataBlockOutput[0], setting); Texture tex = setting.FromBitMap(setting.DataBlockOutput[0], setting);
@ -355,6 +394,12 @@ namespace FirstPlugin
setting.textureData = new TextureData(tex, setting.bntx); setting.textureData = new TextureData(tex, setting.bntx);
} }
int i = 0;
if (Textures.ContainsKey(setting.textureData.Text))
{
setting.textureData.Text = setting.textureData.Text + i++;
}
Nodes.Add(setting.textureData); Nodes.Add(setting.textureData);
Textures.Add(setting.textureData.Text, setting.textureData); Textures.Add(setting.textureData.Text, setting.textureData);
setting.textureData.LoadOpenGLTexture(); setting.textureData.LoadOpenGLTexture();
@ -367,6 +412,7 @@ namespace FirstPlugin
} }
settings.Clear(); settings.Clear();
GC.Collect(); GC.Collect();
Cursor.Current = Cursors.Default;
} }
} }
//This function is an optional feature that will import a dummy texture if one is missing in the materials //This function is an optional feature that will import a dummy texture if one is missing in the materials
@ -500,6 +546,7 @@ namespace FirstPlugin
{ {
Nodes.Clear(); Nodes.Clear();
Textures.Clear(); Textures.Clear();
GC.Collect();
} }
private void ExportAll(object sender, EventArgs args) private void ExportAll(object sender, EventArgs args)
{ {
@ -611,16 +658,26 @@ namespace FirstPlugin
LoadFile(Data); LoadFile(Data);
} }
} }
private void Rename(object sender, EventArgs args)
{
RenameDialog dialog = new RenameDialog();
dialog.SetString(Text);
private void Export(object sender, EventArgs args) if (dialog.ShowDialog() == DialogResult.OK)
{
Text = dialog.textBox1.Text;
}
}
private void Save(object sender, EventArgs args)
{ {
SaveFileDialog sfd = new SaveFileDialog(); SaveFileDialog sfd = new SaveFileDialog();
sfd.DefaultExt = "bntx"; sfd.DefaultExt = "bntx";
sfd.Filter = "Supported Formats|*.bntx;"; sfd.Filter = "Supported Formats|*.bntx;";
sfd.FileName = FileHandler.FileName;
if (sfd.ShowDialog() == DialogResult.OK) if (sfd.ShowDialog() == DialogResult.OK)
{ {
File.WriteAllBytes(sfd.FileName, Data); File.WriteAllBytes(sfd.FileName, FileHandler.Save());
} }
} }
} }
@ -631,8 +688,7 @@ namespace FirstPlugin
public BntxFile bntxFile; public BntxFile bntxFile;
public List<List<byte[]>> mipmaps = new List<List<byte[]>>(); public List<List<byte[]>> mipmaps = new List<List<byte[]>>();
public BRTI_Texture renderedGLTex = new BRTI_Texture(); public BRTI_Texture renderedGLTex = new BRTI_Texture();
public bool GLInitialized = false;
BNTXEditor BNTXEditor;
public TextureData() public TextureData()
{ {
@ -673,11 +729,11 @@ namespace FirstPlugin
} }
public override void OnClick(TreeView treeView) public override void OnClick(TreeView treeView)
{ {
foreach (Control control in FirstPlugin.MainF.Controls) if (FirstPlugin.DockedEditorS == null)
{ {
if (control is DockPanel) foreach (Control control in FirstPlugin.MainF.Controls)
{ {
if (FirstPlugin.DockedEditorS == null) if (control is DockPanel)
{ {
FirstPlugin.DockedEditorS = new DockContent(); FirstPlugin.DockedEditorS = new DockContent();
FirstPlugin.DockedEditorS.Show((DockPanel)control, PluginRuntime.FSHPDockState); FirstPlugin.DockedEditorS.Show((DockPanel)control, PluginRuntime.FSHPDockState);
@ -689,14 +745,24 @@ namespace FirstPlugin
{ {
FirstPlugin.DockedEditorS.Controls.Clear(); FirstPlugin.DockedEditorS.Controls.Clear();
BNTXEditor = new BNTXEditor(); BNTXEditor BNTXEditor = new BNTXEditor();
BNTXEditor.Text = Text; BNTXEditor.Text = Text;
BNTXEditor.Dock = DockStyle.Fill; BNTXEditor.Dock = DockStyle.Fill;
BNTXEditor.LoadPicture(DisplayTexture());
BNTXEditor.LoadProperty(this); BNTXEditor.LoadProperty(this);
FirstPlugin.DockedEditorS.Controls.Add(BNTXEditor); FirstPlugin.DockedEditorS.Controls.Add(BNTXEditor);
} }
} }
public void UpdateEditor()
{
foreach (Control ctrl in FirstPlugin.DockedEditorS.Controls)
{
if (ctrl is BNTXEditor)
{
FirstPlugin.DockedEditorS.Text = Text;
((BNTXEditor)ctrl).LoadProperty(this);
}
}
}
public bool EditorIsActive(DockContent dock) public bool EditorIsActive(DockContent dock)
{ {
foreach (Control ctrl in dock.Controls) foreach (Control ctrl in dock.Controls)
@ -704,7 +770,6 @@ namespace FirstPlugin
if (ctrl is BNTXEditor) if (ctrl is BNTXEditor)
{ {
dock.Text = Text; dock.Text = Text;
((BNTXEditor)ctrl).LoadPicture(DisplayTexture());
((BNTXEditor)ctrl).LoadProperty(this); ((BNTXEditor)ctrl).LoadProperty(this);
return true; return true;
} }
@ -781,6 +846,7 @@ namespace FirstPlugin
break; break;
} }
renderedGLTex.display = loadImage(renderedGLTex); renderedGLTex.display = loadImage(renderedGLTex);
GLInitialized = true;
return renderedGLTex; return renderedGLTex;
} }
@ -793,62 +859,128 @@ namespace FirstPlugin
if (Format == SurfaceFormat.BC5_SNORM) if (Format == SurfaceFormat.BC5_SNORM)
return DDSCompressor.DecompressBC5(data, (int)Width, (int)Height, true); return DDSCompressor.DecompressBC5(data, (int)Width, (int)Height, true);
byte[] d = DecodePixelBlocks(data, (int)Width, (int)Height, Format); byte[] d = null;
d = DecompressBlocks(data, (int)Width, (int)Height, Format); if (IsCompressedFormat(Format))
d = DDSCompressor.DecompressBlock(data, (int)Width, (int)Height, GetCompressedDXGI_FORMAT(Format));
else if (IsAtscFormat(Format))
d = null;
else
d = DDSCompressor.DecodePixelBlock(data, (int)Width, (int)Height, GetUncompressedDXGI_FORMAT(Format));
if (d != null) if (d != null)
{ {
decomp = BitmapExtension.GetBitmap(d, (int)Width, (int)Height); decomp = BitmapExtension.GetBitmap(d, (int)Width, (int)Height);
return SwapBlueRedChannels(decomp); return SwapBlueRedChannels(decomp);
} }
return null; return null;
} }
private static byte[] DecompressBlocks(byte[] data, int width, int height, SurfaceFormat Format) private static DDS.DXGI_FORMAT GetUncompressedDXGI_FORMAT(SurfaceFormat Format)
{ {
switch (Format) switch (Format)
{ {
case SurfaceFormat.BC1_UNORM: return DDSCompressor.DecompressBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM); case SurfaceFormat.A1_B5_G5_R5_UNORM: return DDS.DXGI_FORMAT.DXGI_FORMAT_B5G5R5A1_UNORM;
case SurfaceFormat.BC1_SRGB: return DDSCompressor.DecompressBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM_SRGB); case SurfaceFormat.A4_B4_G4_R4_UNORM: return DDS.DXGI_FORMAT.DXGI_FORMAT_B4G4R4A4_UNORM;
case SurfaceFormat.BC2_UNORM: return DDSCompressor.DecompressBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_BC2_UNORM); case SurfaceFormat.B5_G5_R5_A1_UNORM: return DDS.DXGI_FORMAT.DXGI_FORMAT_B5G5R5A1_UNORM;
case SurfaceFormat.BC2_SRGB: return DDSCompressor.DecompressBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_BC2_UNORM_SRGB); case SurfaceFormat.B5_G6_R5_UNORM: return DDS.DXGI_FORMAT.DXGI_FORMAT_B5G6R5_UNORM;
case SurfaceFormat.BC3_UNORM: return DDSCompressor.DecompressBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_BC3_UNORM); case SurfaceFormat.B8_G8_R8_A8_SRGB: return DDS.DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
case SurfaceFormat.BC3_SRGB: return DDSCompressor.DecompressBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_BC3_UNORM_SRGB); case SurfaceFormat.B8_G8_R8_A8_UNORM: return DDS.DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM;
case SurfaceFormat.BC4_UNORM: return DDSCompressor.DecompressBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_BC4_UNORM); case SurfaceFormat.R10_G10_B10_A2_UNORM: return DDS.DXGI_FORMAT.DXGI_FORMAT_R10G10B10A2_UNORM;
case SurfaceFormat.BC4_SNORM: return DDSCompressor.DecompressBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_BC4_SNORM); case SurfaceFormat.R11_G11_B10_FLOAT: return DDS.DXGI_FORMAT.DXGI_FORMAT_R11G11B10_FLOAT;
case SurfaceFormat.BC5_UNORM: return DDSCompressor.DecompressBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_BC5_UNORM); case SurfaceFormat.R16_UNORM: return DDS.DXGI_FORMAT.DXGI_FORMAT_R16_UNORM;
case SurfaceFormat.BC6_UFLOAT: return DDSCompressor.DecompressBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_BC6H_UF16); case SurfaceFormat.R32_FLOAT: return DDS.DXGI_FORMAT.DXGI_FORMAT_R32_FLOAT;
case SurfaceFormat.BC6_FLOAT: return DDSCompressor.DecompressBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_BC4_SNORM); case SurfaceFormat.R4_G4_B4_A4_UNORM: return DDS.DXGI_FORMAT.DXGI_FORMAT_B4G4R4A4_UNORM;
case SurfaceFormat.BC7_UNORM: return DDSCompressor.DecompressBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_BC7_UNORM); case SurfaceFormat.R4_G4_UNORM: return DDS.DXGI_FORMAT.DXGI_FORMAT_B4G4R4A4_UNORM;
case SurfaceFormat.BC7_SRGB: return DDSCompressor.DecompressBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_BC7_UNORM_SRGB); case SurfaceFormat.R5_G5_B5_A1_UNORM: return DDS.DXGI_FORMAT.DXGI_FORMAT_B5G5R5A1_UNORM;
case SurfaceFormat.R5_G6_B5_UNORM: return DDS.DXGI_FORMAT.DXGI_FORMAT_B5G6R5_UNORM;
case SurfaceFormat.R8_G8_B8_A8_SRGB: return DDS.DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
case SurfaceFormat.R8_G8_B8_A8_UNORM: return DDS.DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM;
case SurfaceFormat.R8_G8_UNORM: return DDS.DXGI_FORMAT.DXGI_FORMAT_R8G8_UNORM;
case SurfaceFormat.R8_UNORM: return DDS.DXGI_FORMAT.DXGI_FORMAT_R8_UNORM;
case SurfaceFormat.Invalid: throw new Exception("Invalid Format");
default: default:
return null; throw new Exception($"Cannot convert format {Format}");
} }
} }
private static byte[] DecodePixelBlocks(byte[] data, int width, int height, SurfaceFormat Format) private static DDS.DXGI_FORMAT GetCompressedDXGI_FORMAT(SurfaceFormat Format)
{ {
switch (Format) switch (Format)
{ {
case SurfaceFormat.A1_B5_G5_R5_UNORM: return DDSCompressor.DecodePixelBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_B5G5R5A1_UNORM); case SurfaceFormat.BC1_UNORM: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM;
case SurfaceFormat.A4_B4_G4_R4_UNORM: return DDSCompressor.DecodePixelBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_B4G4R4A4_UNORM); case SurfaceFormat.BC1_SRGB: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM_SRGB;
case SurfaceFormat.B5_G5_R5_A1_UNORM: return DDSCompressor.DecodePixelBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_B5G5R5A1_UNORM); case SurfaceFormat.BC2_UNORM: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC2_UNORM;
case SurfaceFormat.B5_G6_R5_UNORM: return DDSCompressor.DecodePixelBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_B5G6R5_UNORM); case SurfaceFormat.BC2_SRGB: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC2_UNORM_SRGB;
case SurfaceFormat.B8_G8_R8_A8_SRGB: return DDSCompressor.DecodePixelBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM_SRGB); case SurfaceFormat.BC3_UNORM: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC3_UNORM;
case SurfaceFormat.B8_G8_R8_A8_UNORM: return DDSCompressor.DecodePixelBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM); case SurfaceFormat.BC3_SRGB: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC3_UNORM_SRGB;
case SurfaceFormat.R10_G10_B10_A2_UNORM: return DDSCompressor.DecodePixelBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_R10G10B10A2_UNORM); case SurfaceFormat.BC4_UNORM: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC4_UNORM;
case SurfaceFormat.R11_G11_B10_FLOAT: return DDSCompressor.DecodePixelBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_R11G11B10_FLOAT); case SurfaceFormat.BC4_SNORM: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC4_SNORM;
case SurfaceFormat.R16_UNORM: return DDSCompressor.DecodePixelBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_R16_UNORM); case SurfaceFormat.BC5_UNORM: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC5_UNORM;
case SurfaceFormat.R32_FLOAT: return DDSCompressor.DecodePixelBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_R32_FLOAT); case SurfaceFormat.BC5_SNORM: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC5_SNORM;
case SurfaceFormat.R4_G4_B4_A4_UNORM: return DDSCompressor.DecodePixelBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_B4G4R4A4_UNORM); case SurfaceFormat.BC6_UFLOAT: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC6H_UF16;
case SurfaceFormat.R4_G4_UNORM: return DDSCompressor.DecodePixelBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_B4G4R4A4_UNORM); case SurfaceFormat.BC6_FLOAT: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC6H_SF16;
case SurfaceFormat.R5_G5_B5_A1_UNORM: return DDSCompressor.DecodePixelBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_B5G5R5A1_UNORM); case SurfaceFormat.BC7_UNORM: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC7_UNORM;
case SurfaceFormat.R5_G6_B5_UNORM: return DDSCompressor.DecodePixelBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_B5G6R5_UNORM); case SurfaceFormat.BC7_SRGB: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC7_UNORM_SRGB;
case SurfaceFormat.R8_G8_B8_A8_SRGB: return DDSCompressor.DecodePixelBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM_SRGB); case SurfaceFormat.Invalid: throw new Exception("Invalid Format");
case SurfaceFormat.R8_G8_B8_A8_UNORM: return data;
case SurfaceFormat.R8_G8_UNORM: return DDSCompressor.DecodePixelBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_R8G8_UNORM);
case SurfaceFormat.R8_UNORM: return DDSCompressor.DecodePixelBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_R8_UNORM);
default: default:
return null; throw new Exception($"Cannot convert format {Format}");
}
}
private static bool IsCompressedFormat(SurfaceFormat Format)
{
switch (Format)
{
case SurfaceFormat.BC1_UNORM:
case SurfaceFormat.BC1_SRGB:
case SurfaceFormat.BC2_UNORM:
case SurfaceFormat.BC2_SRGB:
case SurfaceFormat.BC3_UNORM:
case SurfaceFormat.BC3_SRGB:
case SurfaceFormat.BC4_UNORM:
case SurfaceFormat.BC4_SNORM:
case SurfaceFormat.BC5_UNORM:
case SurfaceFormat.BC5_SNORM:
case SurfaceFormat.BC6_UFLOAT:
case SurfaceFormat.BC6_FLOAT:
case SurfaceFormat.BC7_UNORM:
case SurfaceFormat.BC7_SRGB:
return true;
default:
return false;
}
}
private static bool IsAtscFormat(SurfaceFormat Format)
{
switch (Format)
{
case SurfaceFormat.ASTC_10x10_SRGB:
case SurfaceFormat.ASTC_10x10_UNORM:
case SurfaceFormat.ASTC_10x5_SRGB:
case SurfaceFormat.ASTC_10x5_UNORM:
case SurfaceFormat.ASTC_10x6_SRGB:
case SurfaceFormat.ASTC_10x6_UNORM:
case SurfaceFormat.ASTC_10x8_SRGB:
case SurfaceFormat.ASTC_10x8_UNORM:
case SurfaceFormat.ASTC_12x10_SRGB:
case SurfaceFormat.ASTC_12x10_UNORM:
case SurfaceFormat.ASTC_12x12_SRGB:
case SurfaceFormat.ASTC_12x12_UNORM:
case SurfaceFormat.ASTC_4x4_SRGB:
case SurfaceFormat.ASTC_5x4_SRGB:
case SurfaceFormat.ASTC_5x4_UNORM:
case SurfaceFormat.ASTC_5x5_SRGB:
case SurfaceFormat.ASTC_5x5_UNORM:
case SurfaceFormat.ASTC_6x5_SRGB:
case SurfaceFormat.ASTC_6x5_UNORM:
case SurfaceFormat.ASTC_6x6_SRGB:
case SurfaceFormat.ASTC_6x6_UNORM:
case SurfaceFormat.ASTC_8x5_SRGB:
case SurfaceFormat.ASTC_8x5_UNORM:
case SurfaceFormat.ASTC_8x6_SRGB:
case SurfaceFormat.ASTC_8x6_UNORM:
case SurfaceFormat.ASTC_8x8_SRGB:
case SurfaceFormat.ASTC_8x8_UNORM:
return true;
default:
return false;
} }
} }
public static Bitmap SwapBlueRedChannels(Bitmap bitmap) public static Bitmap SwapBlueRedChannels(Bitmap bitmap)
@ -857,45 +989,12 @@ namespace FirstPlugin
} }
public static byte[] CompressBlock(byte[] data, int width, int height, SurfaceFormat format) public static byte[] CompressBlock(byte[] data, int width, int height, SurfaceFormat format)
{ {
switch (format) if (IsCompressedFormat(format))
{ return DDSCompressor.CompressBlock(data, width, height, GetCompressedDXGI_FORMAT(format));
case SurfaceFormat.A1_B5_G5_R5_UNORM: return DDSCompressor.EncodePixelBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_B5G5R5A1_UNORM); else if (IsAtscFormat(format))
case SurfaceFormat.A4_B4_G4_R4_UNORM: return DDSCompressor.EncodePixelBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_B4G4R4A4_UNORM); return null;
case SurfaceFormat.B5_G5_R5_A1_UNORM: return DDSCompressor.EncodePixelBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_B5G5R5A1_UNORM); else
case SurfaceFormat.B5_G6_R5_UNORM: return DDSCompressor.EncodePixelBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_B5G6R5_UNORM); return DDSCompressor.EncodePixelBlock(data, width, height, GetUncompressedDXGI_FORMAT(format));
case SurfaceFormat.B8_G8_R8_A8_SRGB: return DDSCompressor.EncodePixelBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM_SRGB);
case SurfaceFormat.B8_G8_R8_A8_UNORM: return DDSCompressor.EncodePixelBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM);
case SurfaceFormat.R10_G10_B10_A2_UNORM: return DDSCompressor.EncodePixelBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_R10G10B10A2_UNORM);
case SurfaceFormat.R11_G11_B10_FLOAT: return DDSCompressor.EncodePixelBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_R11G11B10_FLOAT);
case SurfaceFormat.R16_UNORM: return DDSCompressor.EncodePixelBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_R16_UNORM);
case SurfaceFormat.R32_FLOAT: return DDSCompressor.EncodePixelBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_R32_FLOAT);
case SurfaceFormat.R4_G4_B4_A4_UNORM: return DDSCompressor.EncodePixelBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_B4G4R4A4_UNORM);
case SurfaceFormat.R4_G4_UNORM: return DDSCompressor.EncodePixelBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_B4G4R4A4_UNORM);
case SurfaceFormat.R5_G5_B5_A1_UNORM: return DDSCompressor.EncodePixelBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_B5G5R5A1_UNORM);
case SurfaceFormat.R5_G6_B5_UNORM: return DDSCompressor.EncodePixelBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_B5G6R5_UNORM);
case SurfaceFormat.R8_G8_B8_A8_SRGB: return DDSCompressor.EncodePixelBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM_SRGB);
case SurfaceFormat.R8_G8_B8_A8_UNORM: return data;
case SurfaceFormat.R8_G8_UNORM: return DDSCompressor.EncodePixelBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_R8G8_UNORM);
case SurfaceFormat.R8_UNORM: return DDSCompressor.EncodePixelBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_R8_UNORM);
case SurfaceFormat.BC1_UNORM: return DDSCompressor.CompressBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM);
case SurfaceFormat.BC1_SRGB: return DDSCompressor.CompressBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM_SRGB);
case SurfaceFormat.BC2_UNORM: return DDSCompressor.CompressBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_BC2_UNORM);
case SurfaceFormat.BC2_SRGB: return DDSCompressor.CompressBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_BC2_UNORM_SRGB);
case SurfaceFormat.BC3_UNORM: return DDSCompressor.CompressBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_BC3_UNORM);
case SurfaceFormat.BC3_SRGB: return DDSCompressor.CompressBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_BC3_UNORM_SRGB);
case SurfaceFormat.BC4_UNORM: return DDSCompressor.CompressBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_BC4_UNORM);
case SurfaceFormat.BC4_SNORM: return DDSCompressor.CompressBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_BC4_SNORM);
case SurfaceFormat.BC5_UNORM: return DDSCompressor.CompressBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_BC5_UNORM);
case SurfaceFormat.BC5_SNORM: return DDSCompressor.CompressBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_BC5_SNORM);
case SurfaceFormat.BC6_UFLOAT: return DDSCompressor.CompressBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_BC6H_UF16);
case SurfaceFormat.BC6_FLOAT: return DDSCompressor.CompressBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_BC6H_SF16);
case SurfaceFormat.BC7_UNORM: return DDSCompressor.CompressBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_BC7_UNORM);
case SurfaceFormat.BC7_SRGB: return DDSCompressor.CompressBlock(data, width, height, DDS.DXGI_FORMAT.DXGI_FORMAT_BC7_UNORM_SRGB);
default:
throw new Exception($"Format {format} unsupported and cannot be compressed!");
}
} }
public unsafe Bitmap GLTextureToBitmap(BRTI_Texture t, int id) public unsafe Bitmap GLTextureToBitmap(BRTI_Texture t, int id)
{ {
@ -990,19 +1089,14 @@ namespace FirstPlugin
private void Replace(object sender, EventArgs args) private void Replace(object sender, EventArgs args)
{ {
OpenFileDialog ofd = new OpenFileDialog(); OpenFileDialog ofd = new OpenFileDialog();
/* ofd.Filter = "Supported Formats|*.bftex;*.dds; *.png;*.tga;*.jpg;*.tiff|" + ofd.Filter = "Supported Formats|*.bftex;*.dds; *.png;*.tga;*.jpg;*.tiff|" +
"Binary Texture |*.bftex|" + "Binary Texture |*.bftex|" +
"Microsoft DDS |*.dds|" + "Microsoft DDS |*.dds|" +
"Portable Network Graphics |*.png|" + "Portable Network Graphics |*.png|" +
"Joint Photographic Experts Group |*.jpg|" + "Joint Photographic Experts Group |*.jpg|" +
"Bitmap Image |*.bmp|" + "Bitmap Image |*.bmp|" +
"Tagged Image File Format |*.tiff|" + "Tagged Image File Format |*.tiff|" +
"All files(*.*)|*.*";*/ "All files(*.*)|*.*";
ofd.Filter = "Supported Formats|*.bftex;*.dds|" +
"Binary Texture |*.bftex|" +
"Microsoft DDS |*.dds|" +
"All files(*.*)|*.*";
ofd.Multiselect = false; ofd.Multiselect = false;
if (ofd.ShowDialog() == DialogResult.OK) if (ofd.ShowDialog() == DialogResult.OK)
@ -1015,26 +1109,47 @@ namespace FirstPlugin
string ext = Path.GetExtension(FileName); string ext = Path.GetExtension(FileName);
ext = ext.ToLower(); ext = ext.ToLower();
TextureImporterSettings setting = new TextureImporterSettings();
BinaryTextureImporterList importer = new BinaryTextureImporterList();
switch (ext) switch (ext)
{ {
case ".bftex": case ".bftex":
Texture.Import(FileName); Texture.Import(FileName);
break; break;
case ".dds": case ".dds":
TextureImporterSettings importDDS = new TextureImporterSettings(); setting.LoadDDS(FileName, bntxFile, null, this);
importDDS.LoadDDS(FileName, bntxFile, null, this);
break; break;
default: default:
TextureImporterSettings import = new TextureImporterSettings(); setting.LoadBitMap(FileName, bntxFile);
import.LoadBitMap(FileName, bntxFile, this); importer.LoadSetting(setting, (BinaryTextureContainer)Parent);
break; break;
} }
Texture.Name = Text;
UpdateBfresTextureMapping(); if (importer.ShowDialog() == DialogResult.OK)
if (BNTXEditor != null)
{ {
BNTXEditor.LoadPicture(DisplayTexture()); Cursor.Current = Cursors.WaitCursor;
BNTXEditor.LoadProperty(this);
if (setting.GenerateMipmaps)
{
setting.DataBlockOutput.Clear();
setting.DataBlockOutput.Add(setting.GenerateMips());
}
if (setting.DataBlockOutput != null)
{
Texture = setting.FromBitMap(setting.DataBlockOutput[0], setting);
LoadTexture(Texture, 1);
LoadOpenGLTexture();
}
else
{
MessageBox.Show("Something went wrong???");
}
Texture.Name = Text;
UpdateBfresTextureMapping();
UpdateEditor();
} }
} }
private void UpdateBfresTextureMapping() private void UpdateBfresTextureMapping()

View file

@ -201,7 +201,7 @@ namespace FirstPlugin
internal void SaveBinaryTexture(string FileName) internal void SaveBinaryTexture(string FileName)
{ {
Console.WriteLine("Test"); Console.WriteLine("Test");
// Texture.Export(FileName, bntxFile); // Texture.Export(FileName, bntxFile);
} }
internal void SaveDDS(string FileName) internal void SaveDDS(string FileName)
{ {
@ -444,48 +444,91 @@ namespace FirstPlugin
byte[] data = renderedTex.mipmaps[ArrayIndex][DisplayMipIndex]; byte[] data = renderedTex.mipmaps[ArrayIndex][DisplayMipIndex];
return DecodeBlock(data, width, height, format); return DecodeBlock(data, width, height, (GX2SurfaceFormat)format);
} }
public static Bitmap DecodeBlock(byte[] data, uint Width, uint Height, int Format) public static Bitmap DecodeBlock(byte[] data, uint Width, uint Height, GX2SurfaceFormat Format)
{ {
Bitmap decomp; Bitmap decomp;
if (Format == GX2SurfaceFormat.T_BC5_SNorm)
return DDSCompressor.DecompressBC5(data, (int)Width, (int)Height, true);
byte[] d = null;
if (IsCompressedFormat(Format))
d = DDSCompressor.DecompressBlock(data, (int)Width, (int)Height, GetCompressedDXGI_FORMAT(Format));
else
d = DDSCompressor.DecodePixelBlock(data, (int)Width, (int)Height, GetUncompressedDXGI_FORMAT(Format));
if (d != null)
{
decomp = BitmapExtension.GetBitmap(d, (int)Width, (int)Height);
return SwapBlueRedChannels(decomp);
}
return null;
}
private static DDS.DXGI_FORMAT GetUncompressedDXGI_FORMAT(GX2SurfaceFormat Format)
{
switch (Format) switch (Format)
{ {
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC1_UNORM): case GX2SurfaceFormat.TC_A1_B5_G5_R5_UNorm: return DDS.DXGI_FORMAT.DXGI_FORMAT_B5G5R5A1_UNORM;
decomp = DDSCompressor.DecompressBC1(data, (int)Width, (int)Height, false); break; case GX2SurfaceFormat.TC_R4_G4_B4_A4_UNorm: return DDS.DXGI_FORMAT.DXGI_FORMAT_B4G4R4A4_UNORM;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC1_SRGB): case GX2SurfaceFormat.TCS_R5_G6_B5_UNorm: return DDS.DXGI_FORMAT.DXGI_FORMAT_B5G6R5_UNORM;
decomp = DDSCompressor.DecompressBC1(data, (int)Width, (int)Height, true); break; case GX2SurfaceFormat.TCS_R8_G8_B8_A8_SRGB: return DDS.DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC3_UNORM): case GX2SurfaceFormat.TCS_R8_G8_B8_A8_UNorm: return DDS.DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM;
decomp = DDSCompressor.DecompressBC3(data, (int)Width, (int)Height, false); break; case GX2SurfaceFormat.TCS_R10_G10_B10_A2_UNorm: return DDS.DXGI_FORMAT.DXGI_FORMAT_R10G10B10A2_UNORM;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC3_SRGB): case GX2SurfaceFormat.TC_R11_G11_B10_Float: return DDS.DXGI_FORMAT.DXGI_FORMAT_R11G11B10_FLOAT;
decomp = DDSCompressor.DecompressBC3(data, (int)Width, (int)Height, true); break; case GX2SurfaceFormat.TCD_R16_UNorm: return DDS.DXGI_FORMAT.DXGI_FORMAT_R16_UNORM;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC4_UNORM): case GX2SurfaceFormat.TCD_R32_Float: return DDS.DXGI_FORMAT.DXGI_FORMAT_R32_FLOAT;
decomp = DDSCompressor.DecompressBC4(data, (int)Width, (int)Height, false); break; case GX2SurfaceFormat.T_R4_G4_UNorm: return DDS.DXGI_FORMAT.DXGI_FORMAT_B4G4R4A4_UNORM;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC4_SNORM): case GX2SurfaceFormat.TC_R8_G8_UNorm: return DDS.DXGI_FORMAT.DXGI_FORMAT_R8G8_UNORM;
decomp = DDSCompressor.DecompressBC4(data, (int)Width, (int)Height, true); break; case GX2SurfaceFormat.TC_R8_UNorm: return DDS.DXGI_FORMAT.DXGI_FORMAT_R8_UNORM;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC5_UNORM): case GX2SurfaceFormat.Invalid: throw new Exception("Invalid Format");
decomp = DDSCompressor.DecompressBC5(data, (int)Width, (int)Height, false); break;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC5_SNORM):
decomp = DDSCompressor.DecompressBC5(data, (int)Width, (int)Height, true); break;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_TC_R8_G8_B8_A8_SNORM):
byte[] dec = DDSCompressor.DecodePixelBlock(data, (int)Width, (int)Height, DDS.DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM_SRGB);
decomp = BitmapExtension.GetBitmap(dec, (int)Width, (int)Height);
decomp = TextureData.SwapBlueRedChannels(decomp);
break;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_TC_R8_G8_B8_A8_UINT):
decomp = BitmapExtension.GetBitmap(data, (int)Width, (int)Height);
decomp = TextureData.SwapBlueRedChannels(decomp);
break;
default: default:
decomp = Properties.Resources.TextureError; throw new Exception($"Cannot convert format {Format}");
Console.WriteLine($"Format {Format} not supported!");
break;
} }
return decomp;
} }
private static bool IsCompressedFormat(GX2SurfaceFormat Format)
{
switch (Format)
{
case GX2SurfaceFormat.T_BC1_UNorm:
case GX2SurfaceFormat.T_BC1_SRGB:
case GX2SurfaceFormat.T_BC2_SRGB:
case GX2SurfaceFormat.T_BC2_UNorm:
case GX2SurfaceFormat.T_BC3_UNorm:
case GX2SurfaceFormat.T_BC3_SRGB:
case GX2SurfaceFormat.T_BC4_UNorm:
case GX2SurfaceFormat.T_BC4_SNorm:
case GX2SurfaceFormat.T_BC5_UNorm:
case GX2SurfaceFormat.T_BC5_SNorm:
return true;
default:
return false;
}
}
private static DDS.DXGI_FORMAT GetCompressedDXGI_FORMAT(GX2SurfaceFormat Format)
{
switch (Format)
{
case GX2SurfaceFormat.T_BC1_UNorm: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM;
case GX2SurfaceFormat.T_BC1_SRGB: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM_SRGB;
case GX2SurfaceFormat.T_BC2_SRGB: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC2_UNORM;
case GX2SurfaceFormat.T_BC2_UNorm: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC2_UNORM_SRGB;
case GX2SurfaceFormat.T_BC3_UNorm: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC3_UNORM;
case GX2SurfaceFormat.T_BC3_SRGB: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC3_UNORM_SRGB;
case GX2SurfaceFormat.T_BC4_UNorm: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC4_UNORM;
case GX2SurfaceFormat.T_BC4_SNorm: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC4_SNORM;
case GX2SurfaceFormat.T_BC5_UNorm: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC5_UNORM;
case GX2SurfaceFormat.T_BC5_SNorm: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC5_SNORM;
default:
throw new Exception($"Cannot convert format {Format}");
}
}
public static Bitmap SwapBlueRedChannels(Bitmap bitmap)
{
return ColorComponentSelector(bitmap, GX2CompSel.ChannelB, GX2CompSel.ChannelG, GX2CompSel.ChannelR, GX2CompSel.ChannelA);
}
public Bitmap UpdateBitmap(Bitmap image) public Bitmap UpdateBitmap(Bitmap image)
{ {
return ColorComponentSelector(image, ChannelRed, ChannelGreen, ChannelBlue, ChannelAlpha); return ColorComponentSelector(image, ChannelRed, ChannelGreen, ChannelBlue, ChannelAlpha);
@ -502,9 +545,9 @@ namespace FirstPlugin
if (R == GX2CompSel.ChannelA) if (R == GX2CompSel.ChannelA)
color.CompRed = BitmapExtension.ColorSwapFilter.Red.Alpha; color.CompRed = BitmapExtension.ColorSwapFilter.Red.Alpha;
if (R == GX2CompSel.Always0) if (R == GX2CompSel.Always0)
color.CompRed = BitmapExtension.ColorSwapFilter.Red.One;
if (R == GX2CompSel.Always1)
color.CompRed = BitmapExtension.ColorSwapFilter.Red.Zero; color.CompRed = BitmapExtension.ColorSwapFilter.Red.Zero;
if (R == GX2CompSel.Always1)
color.CompRed = BitmapExtension.ColorSwapFilter.Red.One;
if (G == GX2CompSel.ChannelR) if (G == GX2CompSel.ChannelR)
color.CompGreen = BitmapExtension.ColorSwapFilter.Green.Red; color.CompGreen = BitmapExtension.ColorSwapFilter.Green.Red;
@ -515,9 +558,9 @@ namespace FirstPlugin
if (G == GX2CompSel.ChannelA) if (G == GX2CompSel.ChannelA)
color.CompGreen = BitmapExtension.ColorSwapFilter.Green.Alpha; color.CompGreen = BitmapExtension.ColorSwapFilter.Green.Alpha;
if (G == GX2CompSel.Always0) if (G == GX2CompSel.Always0)
color.CompGreen = BitmapExtension.ColorSwapFilter.Green.One;
if (G == GX2CompSel.Always1)
color.CompGreen = BitmapExtension.ColorSwapFilter.Green.Zero; color.CompGreen = BitmapExtension.ColorSwapFilter.Green.Zero;
if (G == GX2CompSel.Always1)
color.CompGreen = BitmapExtension.ColorSwapFilter.Green.One;
if (B == GX2CompSel.ChannelR) if (B == GX2CompSel.ChannelR)
color.CompBlue = BitmapExtension.ColorSwapFilter.Blue.Red; color.CompBlue = BitmapExtension.ColorSwapFilter.Blue.Red;
@ -528,9 +571,9 @@ namespace FirstPlugin
if (B == GX2CompSel.ChannelA) if (B == GX2CompSel.ChannelA)
color.CompBlue = BitmapExtension.ColorSwapFilter.Blue.Alpha; color.CompBlue = BitmapExtension.ColorSwapFilter.Blue.Alpha;
if (B == GX2CompSel.Always0) if (B == GX2CompSel.Always0)
color.CompBlue = BitmapExtension.ColorSwapFilter.Blue.One;
if (B == GX2CompSel.Always1)
color.CompBlue = BitmapExtension.ColorSwapFilter.Blue.Zero; color.CompBlue = BitmapExtension.ColorSwapFilter.Blue.Zero;
if (B == GX2CompSel.Always1)
color.CompBlue = BitmapExtension.ColorSwapFilter.Blue.One;
if (A == GX2CompSel.ChannelR) if (A == GX2CompSel.ChannelR)
color.CompAlpha = BitmapExtension.ColorSwapFilter.Alpha.Red; color.CompAlpha = BitmapExtension.ColorSwapFilter.Alpha.Red;
@ -541,9 +584,9 @@ namespace FirstPlugin
if (A == GX2CompSel.ChannelA) if (A == GX2CompSel.ChannelA)
color.CompAlpha = BitmapExtension.ColorSwapFilter.Alpha.Alpha; color.CompAlpha = BitmapExtension.ColorSwapFilter.Alpha.Alpha;
if (A == GX2CompSel.Always0) if (A == GX2CompSel.Always0)
color.CompAlpha = BitmapExtension.ColorSwapFilter.Alpha.One;
if (A == GX2CompSel.Always1)
color.CompAlpha = BitmapExtension.ColorSwapFilter.Alpha.Zero; color.CompAlpha = BitmapExtension.ColorSwapFilter.Alpha.Zero;
if (A == GX2CompSel.Always1)
color.CompAlpha = BitmapExtension.ColorSwapFilter.Alpha.One;
return BitmapExtension.SwapRGB(image, color); return BitmapExtension.SwapRGB(image, color);
} }

View file

@ -33,10 +33,8 @@ namespace FirstPlugin
public Shader shader = null; public Shader shader = null;
public List<FMDL> models = new List<FMDL>(); public List<FMDL> models = new List<FMDL>();
public AnimationGroupNode SkeletonAnimGroup;
public ResourceFile ResFileNode; public ResourceFile ResFileNode;
public Action SaveFile;
public BFRESRender() public BFRESRender()
{ {
@ -492,7 +490,8 @@ namespace FirstPlugin
{ {
if (bntx.Textures.ContainsKey(t.Name)) if (bntx.Textures.ContainsKey(t.Name))
{ {
bntx.Textures[t.Name].LoadOpenGLTexture(); if (!bntx.Textures[t.Name].GLInitialized)
bntx.Textures[t.Name].LoadOpenGLTexture();
} }
} }
} }
@ -506,9 +505,13 @@ namespace FirstPlugin
foreach (BinaryTextureContainer bntx in PluginRuntime.bntxContainers) foreach (BinaryTextureContainer bntx in PluginRuntime.bntxContainers)
{ {
foreach (var tex in bntx.Textures) if (!bntx.AllGLInitialized)
{ {
tex.Value.LoadOpenGLTexture(); foreach (var tex in bntx.Textures)
{
if (!tex.Value.GLInitialized)
tex.Value.LoadOpenGLTexture();
}
} }
} }
foreach (FTEXContainer ftexCont in PluginRuntime.ftexContainers) foreach (FTEXContainer ftexCont in PluginRuntime.ftexContainers)

View file

@ -19,7 +19,6 @@ namespace FirstPlugin
public void LoadTexture(TextureData tex) public void LoadTexture(TextureData tex)
{ {
TextureData.BRTI_Texture renderedTex = tex.renderedGLTex; TextureData.BRTI_Texture renderedTex = tex.renderedGLTex;
bntxEditor1.LoadPicture(tex.GLTextureToBitmap(renderedTex, renderedTex.display));
bntxEditor1.LoadProperty(tex); bntxEditor1.LoadProperty(tex);
} }
} }

View file

@ -28,16 +28,15 @@ namespace FirstPlugin
imageBGComboBox.SelectedItem = Runtime.pictureBoxStyle; imageBGComboBox.SelectedItem = Runtime.pictureBoxStyle;
UpdateBackgroundImage(); UpdateBackgroundImage();
} }
public void LoadPicture(Bitmap image)
{
// pictureBoxCustom1.Image = image;
}
TextureData textureData; TextureData textureData;
int CurMipDisplayLevel = 0; int CurMipDisplayLevel = 0;
int CurArrayDisplayLevel = 0; int CurArrayDisplayLevel = 0;
public void LoadProperty(TextureData tex) public void LoadProperty(TextureData tex)
{ {
pictureBoxCustom1.Image = Imaging.GetLoadingImage();
LoadImage();
CurMipDisplayLevel = 0; CurMipDisplayLevel = 0;
CurArrayDisplayLevel = 0; CurArrayDisplayLevel = 0;
@ -48,11 +47,8 @@ namespace FirstPlugin
propertyGrid1.SelectedObject = texture; propertyGrid1.SelectedObject = texture;
UpdateMipDisplay(); UpdateMipDisplay();
} }
private void UpdateMipDisplay() private void LoadImage()
{ {
mipLevelCounterLabel.Text = $"{CurMipDisplayLevel} / {textureData.mipmaps[CurArrayDisplayLevel].Count - 1}";
arrayLevelCounterLabel.Text = $"{CurArrayDisplayLevel} / {textureData.mipmaps.Count - 1}";
if (Thread != null && Thread.IsAlive) if (Thread != null && Thread.IsAlive)
Thread.Abort(); Thread.Abort();
@ -60,13 +56,26 @@ namespace FirstPlugin
{ {
pictureBoxCustom1.Image = Imaging.GetLoadingImage(); pictureBoxCustom1.Image = Imaging.GetLoadingImage();
pictureBoxCustom1.Image = textureData.DisplayTexture(CurMipDisplayLevel, CurArrayDisplayLevel); pictureBoxCustom1.Image = textureData.DisplayTexture(CurMipDisplayLevel, CurArrayDisplayLevel);
// texSizeMipsLabel.Text = $"Width = {pictureBoxCustom1.Image.Width} Height = {pictureBoxCustom1.Image.Height}";
})); }));
Thread.Start(); Thread.Start();
GC.Collect();
}
private void UpdateMipDisplay()
{
LoadImage();
if (CurMipDisplayLevel != textureData.mipmaps[CurArrayDisplayLevel].Count - 1) int MipCount = 1;
if (textureData.mipmaps.Count <= 0)
return;
else
MipCount = textureData.mipmaps[CurArrayDisplayLevel].Count;
mipLevelCounterLabel.Text = $"{CurMipDisplayLevel} / {textureData.mipmaps[CurArrayDisplayLevel].Count - 1}";
arrayLevelCounterLabel.Text = $"{CurArrayDisplayLevel} / {textureData.mipmaps.Count - 1}";
if (CurMipDisplayLevel != MipCount - 1)
BtnMipsRight.Enabled = true; BtnMipsRight.Enabled = true;
else else
BtnMipsRight.Enabled = false; BtnMipsRight.Enabled = false;

View file

@ -79,10 +79,20 @@ namespace FirstPlugin
foreach (var setting in settings) foreach (var setting in settings)
{ {
listViewCustom1.Items.Add(setting.TexName).SubItems.Add(setting.Format.ToString()); listViewCustom1.Items.Add(setting.TexName).SubItems.Add(setting.Format.ToString());
} }
listViewCustom1.Items[0].Selected = true;
listViewCustom1.Select();
} }
public void LoadSetting(TextureImporterSettings setting, BinaryTextureContainer b)
{
settings = new List<TextureImporterSettings>();
settings.Add(setting);
bntx = b;
listViewCustom1.Items.Add(setting.TexName).SubItems.Add(setting.Format.ToString());
listViewCustom1.Items[0].Selected = true;
listViewCustom1.Select();
}
public bool IsCompressed(SurfaceFormat format) public bool IsCompressed(SurfaceFormat format)
{ {
switch (format) switch (format)
@ -163,18 +173,8 @@ namespace FirstPlugin
SetupSettings(); SetupSettings();
MipmapNum.Value = 0; MipmapNum.Maximum = SelectedTexSettings.GetTotalMipCount();
MipmapNum.Value = SelectedTexSettings.MipCount;
uint num = Math.Max(SelectedTexSettings.TexHeight, SelectedTexSettings.TexWidth);
while (true)
{
num >>= 1;
if (num > 0)
++MipmapNum.Value;
else
break;
}
MipmapNum.Maximum = MipmapNum.Value;
} }
} }

View file

@ -52,6 +52,7 @@ namespace FirstPlugin
public int sparseResidency = 0; //false public int sparseResidency = 0; //false
public int sparseBinding = 0; //false public int sparseBinding = 0; //false
public bool IsSRGB = true; public bool IsSRGB = true;
public bool GenerateMipmaps = false; //If bitmap and count more that 1 then geenrate
private SurfaceFormat LoadDDSFormat(string fourCC, DDS dds = null, bool IsSRGB = false) private SurfaceFormat LoadDDSFormat(string fourCC, DDS dds = null, bool IsSRGB = false)
{ {
@ -135,6 +136,11 @@ namespace FirstPlugin
MipCount = dds.header.mipmapCount; MipCount = dds.header.mipmapCount;
TexWidth = dds.header.width; TexWidth = dds.header.width;
TexHeight = dds.header.height; TexHeight = dds.header.height;
arrayLength = 1;
if (dds.header.caps2 == (uint)DDS.DDSCAPS2.CUBEMAP_ALLFACES)
{
arrayLength = 6;
}
DataBlockOutput.Add(dds.bdata); DataBlockOutput.Add(dds.bdata);
@ -152,27 +158,22 @@ namespace FirstPlugin
textureData = new TextureData(tex, bntxFile); textureData = new TextureData(tex, bntxFile);
} }
} }
public void LoadBitMap(string FileName, BntxFile bntxFile, TextureData tree = null) public void LoadBitMap(string FileName, BntxFile bntxFile)
{ {
DecompressedData.Clear(); DecompressedData.Clear();
TexName = Path.GetFileNameWithoutExtension(FileName); TexName = Path.GetFileNameWithoutExtension(FileName);
bntx = bntxFile; bntx = bntxFile;
textureData = tree;
Format = SurfaceFormat.BC1_SRGB; Format = SurfaceFormat.BC1_SRGB;
GenerateMipmaps = true;
Bitmap Image = new Bitmap(FileName); Bitmap Image = new Bitmap(FileName);
Image = TextureData.SwapBlueRedChannels(Image); Image = TextureData.SwapBlueRedChannels(Image);
TexWidth = (uint)Image.Width; TexWidth = (uint)Image.Width;
TexHeight = (uint)Image.Height; TexHeight = (uint)Image.Height;
MipCount = 1; MipCount = (uint)GetTotalMipCount();
List<byte[]> mipMaps = new List<byte[]>();
/* while(Image.Width / 2 > 0)
{
Image.SetResolution(Image.Width / 2, Image.Height / 2);
}*/
DecompressedData.Add(BitmapExtension.ImageToByte(Image)); DecompressedData.Add(BitmapExtension.ImageToByte(Image));
Image.Dispose(); Image.Dispose();
@ -181,6 +182,49 @@ namespace FirstPlugin
throw new Exception("Failed to load " + Format); throw new Exception("Failed to load " + Format);
} }
} }
public int GetTotalMipCount()
{
int MipmapNum = 0;
uint num = Math.Max(TexHeight, TexWidth);
int width = (int)TexWidth;
int height = (int)TexHeight;
while (true)
{
num >>= 1;
width = width / 2;
height = height / 2;
if (width <= 0 || height <= 0)
break;
if (num > 0)
++MipmapNum;
else
break;
}
return MipmapNum;
}
public byte[] GenerateMips(int SurfaceLevel = 0)
{
Bitmap Image = BitmapExtension.GetBitmap(DecompressedData[SurfaceLevel], (int)TexWidth, (int)TexHeight);
List<byte[]> mipmaps = new List<byte[]>();
mipmaps.Add(TextureData.CompressBlock(DecompressedData[SurfaceLevel], (int)TexWidth, (int)TexHeight, Format));
//while (Image.Width / 2 > 0 && Image.Height / 2 > 0)
// for (int mipLevel = 0; mipLevel < MipCount; mipLevel++)
for (int mipLevel = 0; mipLevel < MipCount; mipLevel++)
{
Image = BitmapExtension.Resize(Image, Image.Width / 2, Image.Height / 2);
mipmaps.Add(TextureData.CompressBlock(BitmapExtension.ImageToByte(Image), Image.Width, Image.Height, Format));
}
Image.Dispose();
return Utils.CombineByteArray(mipmaps.ToArray());
}
public void Compress() public void Compress()
{ {
DataBlockOutput.Clear(); DataBlockOutput.Clear();
@ -254,11 +298,19 @@ namespace FirstPlugin
tex.MipOffsets = new long[tex.MipCount]; tex.MipOffsets = new long[tex.MipCount];
List<byte[]> mipmaps = SwizzleSurfaceMipMaps(tex, data, tex.TileMode); List<byte[]> arrayFaces = new List<byte[]>();
tex.TextureData.Add(mipmaps); if (tex.ArrayLength > 1)
byte[] test = Combine(mipmaps); arrayFaces = DDS.GetArrayFaces(data, tex.ArrayLength);
tex.TextureData[0][0] = test; else
arrayFaces.Add(data);
for (int i = 0; i < tex.ArrayLength; i++)
{
List<byte[]> mipmaps = SwizzleSurfaceMipMaps(tex, arrayFaces[i], tex.TileMode);
tex.TextureData.Add(mipmaps);
byte[] test = Combine(mipmaps);
tex.TextureData[i][0] = test;
}
return tex; return tex;
} }
public static List<byte[]> SwizzleSurfaceMipMaps(FTEX tex, byte[] data) public static List<byte[]> SwizzleSurfaceMipMaps(FTEX tex, byte[] data)

View file

@ -16,32 +16,73 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GL_Core", "GL_EditorFramewo
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Updater", "Updater\Updater.csproj", "{D82A2C08-2A65-43AF-BDA6-A36CC27AA003}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Updater", "Updater\Updater.csproj", "{D82A2C08-2A65-43AF-BDA6-A36CC27AA003}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTex", "Switch_Toolbox\Lib\DirectXTex\DirectXTex.vcxproj", "{755AB64B-16B4-4C90-AA3B-BFF448E5A21E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DirectXTexNet", "DirectXTexNet-master\DirectXTexNet\DirectXTexNet.csproj", "{98495BF2-DED3-4E08-B965-C12D471BC86F}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Release|Any CPU = Release|Any CPU Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{E861C28B-B039-48F7-9A4F-C83F67C0ADDE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E861C28B-B039-48F7-9A4F-C83F67C0ADDE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E861C28B-B039-48F7-9A4F-C83F67C0ADDE}.Debug|Any CPU.Build.0 = Debug|Any CPU {E861C28B-B039-48F7-9A4F-C83F67C0ADDE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E861C28B-B039-48F7-9A4F-C83F67C0ADDE}.Debug|x64.ActiveCfg = Debug|Any CPU
{E861C28B-B039-48F7-9A4F-C83F67C0ADDE}.Debug|x64.Build.0 = Debug|Any CPU
{E861C28B-B039-48F7-9A4F-C83F67C0ADDE}.Release|Any CPU.ActiveCfg = Release|Any CPU {E861C28B-B039-48F7-9A4F-C83F67C0ADDE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E861C28B-B039-48F7-9A4F-C83F67C0ADDE}.Release|Any CPU.Build.0 = Release|Any CPU {E861C28B-B039-48F7-9A4F-C83F67C0ADDE}.Release|Any CPU.Build.0 = Release|Any CPU
{E861C28B-B039-48F7-9A4F-C83F67C0ADDE}.Release|x64.ActiveCfg = Release|Any CPU
{E861C28B-B039-48F7-9A4F-C83F67C0ADDE}.Release|x64.Build.0 = Release|Any CPU
{A11705CF-A6A3-41C3-875A-E1CFD8080F09}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A11705CF-A6A3-41C3-875A-E1CFD8080F09}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A11705CF-A6A3-41C3-875A-E1CFD8080F09}.Debug|Any CPU.Build.0 = Debug|Any CPU {A11705CF-A6A3-41C3-875A-E1CFD8080F09}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A11705CF-A6A3-41C3-875A-E1CFD8080F09}.Debug|x64.ActiveCfg = Debug|Any CPU
{A11705CF-A6A3-41C3-875A-E1CFD8080F09}.Debug|x64.Build.0 = Debug|Any CPU
{A11705CF-A6A3-41C3-875A-E1CFD8080F09}.Release|Any CPU.ActiveCfg = Release|Any CPU {A11705CF-A6A3-41C3-875A-E1CFD8080F09}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A11705CF-A6A3-41C3-875A-E1CFD8080F09}.Release|Any CPU.Build.0 = Release|Any CPU {A11705CF-A6A3-41C3-875A-E1CFD8080F09}.Release|Any CPU.Build.0 = Release|Any CPU
{A11705CF-A6A3-41C3-875A-E1CFD8080F09}.Release|x64.ActiveCfg = Release|Any CPU
{A11705CF-A6A3-41C3-875A-E1CFD8080F09}.Release|x64.Build.0 = Release|Any CPU
{96820047-2A39-4E5A-BFA4-E84FFF5C66CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {96820047-2A39-4E5A-BFA4-E84FFF5C66CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{96820047-2A39-4E5A-BFA4-E84FFF5C66CF}.Debug|Any CPU.Build.0 = Debug|Any CPU {96820047-2A39-4E5A-BFA4-E84FFF5C66CF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{96820047-2A39-4E5A-BFA4-E84FFF5C66CF}.Debug|x64.ActiveCfg = Debug|Any CPU
{96820047-2A39-4E5A-BFA4-E84FFF5C66CF}.Debug|x64.Build.0 = Debug|Any CPU
{96820047-2A39-4E5A-BFA4-E84FFF5C66CF}.Release|Any CPU.ActiveCfg = Release|Any CPU {96820047-2A39-4E5A-BFA4-E84FFF5C66CF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{96820047-2A39-4E5A-BFA4-E84FFF5C66CF}.Release|Any CPU.Build.0 = Release|Any CPU {96820047-2A39-4E5A-BFA4-E84FFF5C66CF}.Release|Any CPU.Build.0 = Release|Any CPU
{96820047-2A39-4E5A-BFA4-E84FFF5C66CF}.Release|x64.ActiveCfg = Release|Any CPU
{96820047-2A39-4E5A-BFA4-E84FFF5C66CF}.Release|x64.Build.0 = Release|Any CPU
{29647BA5-2859-46F0-A99E-C3A387A9447A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {29647BA5-2859-46F0-A99E-C3A387A9447A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{29647BA5-2859-46F0-A99E-C3A387A9447A}.Debug|Any CPU.Build.0 = Debug|Any CPU {29647BA5-2859-46F0-A99E-C3A387A9447A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{29647BA5-2859-46F0-A99E-C3A387A9447A}.Debug|x64.ActiveCfg = Debug|Any CPU
{29647BA5-2859-46F0-A99E-C3A387A9447A}.Debug|x64.Build.0 = Debug|Any CPU
{29647BA5-2859-46F0-A99E-C3A387A9447A}.Release|Any CPU.ActiveCfg = Release|Any CPU {29647BA5-2859-46F0-A99E-C3A387A9447A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{29647BA5-2859-46F0-A99E-C3A387A9447A}.Release|Any CPU.Build.0 = Release|Any CPU {29647BA5-2859-46F0-A99E-C3A387A9447A}.Release|Any CPU.Build.0 = Release|Any CPU
{29647BA5-2859-46F0-A99E-C3A387A9447A}.Release|x64.ActiveCfg = Release|Any CPU
{29647BA5-2859-46F0-A99E-C3A387A9447A}.Release|x64.Build.0 = Release|Any CPU
{D82A2C08-2A65-43AF-BDA6-A36CC27AA003}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D82A2C08-2A65-43AF-BDA6-A36CC27AA003}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D82A2C08-2A65-43AF-BDA6-A36CC27AA003}.Debug|Any CPU.Build.0 = Debug|Any CPU {D82A2C08-2A65-43AF-BDA6-A36CC27AA003}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D82A2C08-2A65-43AF-BDA6-A36CC27AA003}.Debug|x64.ActiveCfg = Debug|Any CPU
{D82A2C08-2A65-43AF-BDA6-A36CC27AA003}.Debug|x64.Build.0 = Debug|Any CPU
{D82A2C08-2A65-43AF-BDA6-A36CC27AA003}.Release|Any CPU.ActiveCfg = Release|Any CPU {D82A2C08-2A65-43AF-BDA6-A36CC27AA003}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D82A2C08-2A65-43AF-BDA6-A36CC27AA003}.Release|Any CPU.Build.0 = Release|Any CPU {D82A2C08-2A65-43AF-BDA6-A36CC27AA003}.Release|Any CPU.Build.0 = Release|Any CPU
{D82A2C08-2A65-43AF-BDA6-A36CC27AA003}.Release|x64.ActiveCfg = Release|Any CPU
{D82A2C08-2A65-43AF-BDA6-A36CC27AA003}.Release|x64.Build.0 = Release|Any CPU
{755AB64B-16B4-4C90-AA3B-BFF448E5A21E}.Debug|Any CPU.ActiveCfg = Debug|x64
{755AB64B-16B4-4C90-AA3B-BFF448E5A21E}.Debug|x64.ActiveCfg = Debug|x64
{755AB64B-16B4-4C90-AA3B-BFF448E5A21E}.Debug|x64.Build.0 = Debug|x64
{755AB64B-16B4-4C90-AA3B-BFF448E5A21E}.Release|Any CPU.ActiveCfg = Release|Win32
{755AB64B-16B4-4C90-AA3B-BFF448E5A21E}.Release|Any CPU.Build.0 = Release|Win32
{755AB64B-16B4-4C90-AA3B-BFF448E5A21E}.Release|x64.ActiveCfg = Release|x64
{755AB64B-16B4-4C90-AA3B-BFF448E5A21E}.Release|x64.Build.0 = Release|x64
{98495BF2-DED3-4E08-B965-C12D471BC86F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{98495BF2-DED3-4E08-B965-C12D471BC86F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{98495BF2-DED3-4E08-B965-C12D471BC86F}.Debug|x64.ActiveCfg = Debug|Any CPU
{98495BF2-DED3-4E08-B965-C12D471BC86F}.Debug|x64.Build.0 = Debug|Any CPU
{98495BF2-DED3-4E08-B965-C12D471BC86F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{98495BF2-DED3-4E08-B965-C12D471BC86F}.Release|Any CPU.Build.0 = Release|Any CPU
{98495BF2-DED3-4E08-B965-C12D471BC86F}.Release|x64.ActiveCfg = Release|Any CPU
{98495BF2-DED3-4E08-B965-C12D471BC86F}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View file

@ -56,6 +56,9 @@ namespace Switch_Toolbox
case "RenderModelWireframe": case "RenderModelWireframe":
bool.TryParse(node.InnerText, out Runtime.RenderModelWireframe); bool.TryParse(node.InnerText, out Runtime.RenderModelWireframe);
break; break;
case "EnablePBR":
bool.TryParse(node.InnerText, out Runtime.EnablePBR);
break;
case "viewportShading": case "viewportShading":
if (node.ParentNode != null && node.ParentNode.Name.Equals("RENDERSETTINGS")) if (node.ParentNode != null && node.ParentNode.Name.Equals("RENDERSETTINGS"))
Enum.TryParse(node.InnerText, out Runtime.viewportShading); Enum.TryParse(node.InnerText, out Runtime.viewportShading);
@ -78,6 +81,7 @@ namespace Switch_Toolbox
case "Yaz0CompressionLevel": case "Yaz0CompressionLevel":
int.TryParse(node.InnerText, out Runtime.Yaz0CompressionLevel); int.TryParse(node.InnerText, out Runtime.Yaz0CompressionLevel);
break; break;
} }
} }
} }
@ -127,6 +131,7 @@ namespace Switch_Toolbox
renderSettingsNode.AppendChild(createNode(doc, "CameraFar", Runtime.CameraFar.ToString())); renderSettingsNode.AppendChild(createNode(doc, "CameraFar", Runtime.CameraFar.ToString()));
renderSettingsNode.AppendChild(createNode(doc, "CameraNear", Runtime.CameraNear.ToString())); renderSettingsNode.AppendChild(createNode(doc, "CameraNear", Runtime.CameraNear.ToString()));
renderSettingsNode.AppendChild(createNode(doc, "PreviewScale", Runtime.previewScale.ToString())); renderSettingsNode.AppendChild(createNode(doc, "PreviewScale", Runtime.previewScale.ToString()));
renderSettingsNode.AppendChild(createNode(doc, "EnablePBR", Runtime.EnablePBR.ToString()));
} }
public static XmlNode createNode(XmlDocument doc, string el, string v) public static XmlNode createNode(XmlDocument doc, string el, string v)
{ {

View file

@ -48,13 +48,14 @@
this.chkBoxStereoscopy = new System.Windows.Forms.CheckBox(); this.chkBoxStereoscopy = new System.Windows.Forms.CheckBox();
this.label2 = new System.Windows.Forms.Label(); this.label2 = new System.Windows.Forms.Label();
this.panel1 = new System.Windows.Forms.Panel(); this.panel1 = new System.Windows.Forms.Panel();
this.disableViewportCHKBX = new System.Windows.Forms.CheckBox();
this.GLSLVerLabel = new System.Windows.Forms.Label(); this.GLSLVerLabel = new System.Windows.Forms.Label();
this.openGLVerLabel = new System.Windows.Forms.Label(); this.openGLVerLabel = new System.Windows.Forms.Label();
this.btnSave = new System.Windows.Forms.Button(); this.btnSave = new System.Windows.Forms.Button();
this.label7 = new System.Windows.Forms.Label(); this.label7 = new System.Windows.Forms.Label();
this.yazoCompressionLevelUD = new System.Windows.Forms.NumericUpDown(); this.yazoCompressionLevelUD = new System.Windows.Forms.NumericUpDown();
this.panel3 = new System.Windows.Forms.Panel(); this.panel3 = new System.Windows.Forms.Panel();
this.disableViewportCHKBX = new System.Windows.Forms.CheckBox(); this.chkBoxEnablePBR = new System.Windows.Forms.CheckBox();
this.panel2.SuspendLayout(); this.panel2.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.previewScaleUD)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.previewScaleUD)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.camFarNumUD)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.camFarNumUD)).BeginInit();
@ -111,6 +112,7 @@
// //
// panel2 // panel2
// //
this.panel2.Controls.Add(this.chkBoxEnablePBR);
this.panel2.Controls.Add(this.label6); this.panel2.Controls.Add(this.label6);
this.panel2.Controls.Add(this.previewScaleUD); this.panel2.Controls.Add(this.previewScaleUD);
this.panel2.Controls.Add(this.chkBoxDisplayPolyCount); this.panel2.Controls.Add(this.chkBoxDisplayPolyCount);
@ -332,6 +334,18 @@
this.panel1.Size = new System.Drawing.Size(215, 137); this.panel1.Size = new System.Drawing.Size(215, 137);
this.panel1.TabIndex = 5; this.panel1.TabIndex = 5;
// //
// disableViewportCHKBX
//
this.disableViewportCHKBX.AutoSize = true;
this.disableViewportCHKBX.ForeColor = System.Drawing.Color.White;
this.disableViewportCHKBX.Location = new System.Drawing.Point(0, 67);
this.disableViewportCHKBX.Name = "disableViewportCHKBX";
this.disableViewportCHKBX.Size = new System.Drawing.Size(105, 17);
this.disableViewportCHKBX.TabIndex = 16;
this.disableViewportCHKBX.Text = "Disable Viewport";
this.disableViewportCHKBX.UseVisualStyleBackColor = true;
this.disableViewportCHKBX.CheckedChanged += new System.EventHandler(this.checkBox1_CheckedChanged_2);
//
// GLSLVerLabel // GLSLVerLabel
// //
this.GLSLVerLabel.AutoSize = true; this.GLSLVerLabel.AutoSize = true;
@ -404,17 +418,17 @@
this.panel3.Size = new System.Drawing.Size(313, 138); this.panel3.Size = new System.Drawing.Size(313, 138);
this.panel3.TabIndex = 18; this.panel3.TabIndex = 18;
// //
// disableViewportCHKBX // chkBoxEnablePBR
// //
this.disableViewportCHKBX.AutoSize = true; this.chkBoxEnablePBR.AutoSize = true;
this.disableViewportCHKBX.ForeColor = System.Drawing.Color.White; this.chkBoxEnablePBR.ForeColor = System.Drawing.Color.White;
this.disableViewportCHKBX.Location = new System.Drawing.Point(0, 67); this.chkBoxEnablePBR.Location = new System.Drawing.Point(258, 139);
this.disableViewportCHKBX.Name = "disableViewportCHKBX"; this.chkBoxEnablePBR.Name = "chkBoxEnablePBR";
this.disableViewportCHKBX.Size = new System.Drawing.Size(105, 17); this.chkBoxEnablePBR.Size = new System.Drawing.Size(84, 17);
this.disableViewportCHKBX.TabIndex = 16; this.chkBoxEnablePBR.TabIndex = 17;
this.disableViewportCHKBX.Text = "Disable Viewport"; this.chkBoxEnablePBR.Text = "Enable PBR";
this.disableViewportCHKBX.UseVisualStyleBackColor = true; this.chkBoxEnablePBR.UseVisualStyleBackColor = true;
this.disableViewportCHKBX.CheckedChanged += new System.EventHandler(this.checkBox1_CheckedChanged_2); this.chkBoxEnablePBR.CheckedChanged += new System.EventHandler(this.chkBoxEnablePBR_CheckedChanged);
// //
// Settings // Settings
// //
@ -473,5 +487,6 @@
private System.Windows.Forms.NumericUpDown yazoCompressionLevelUD; private System.Windows.Forms.NumericUpDown yazoCompressionLevelUD;
private System.Windows.Forms.Panel panel3; private System.Windows.Forms.Panel panel3;
private System.Windows.Forms.CheckBox disableViewportCHKBX; private System.Windows.Forms.CheckBox disableViewportCHKBX;
private System.Windows.Forms.CheckBox chkBoxEnablePBR;
} }
} }

View file

@ -45,6 +45,7 @@ namespace Switch_Toolbox
previewScaleUD.Value = (decimal)Runtime.previewScale; previewScaleUD.Value = (decimal)Runtime.previewScale;
yazoCompressionLevelUD.Value = Runtime.Yaz0CompressionLevel; yazoCompressionLevelUD.Value = Runtime.Yaz0CompressionLevel;
disableViewportCHKBX.Checked = Runtime.DisableViewport; disableViewportCHKBX.Checked = Runtime.DisableViewport;
chkBoxEnablePBR.Checked = Runtime.EnablePBR;
GLSLVerLabel.Text = $"Open GL Version: {Runtime.GLSLVersion}"; GLSLVerLabel.Text = $"Open GL Version: {Runtime.GLSLVersion}";
openGLVerLabel.Text = $"GLSL Version: {Runtime.openGLVersion}"; openGLVerLabel.Text = $"GLSL Version: {Runtime.openGLVersion}";
@ -139,5 +140,10 @@ namespace Switch_Toolbox
{ {
Runtime.DisableViewport = disableViewportCHKBX.Checked; Runtime.DisableViewport = disableViewportCHKBX.Checked;
} }
private void chkBoxEnablePBR_CheckedChanged(object sender, EventArgs e)
{
Runtime.EnablePBR = chkBoxEnablePBR.Checked;
}
} }
} }

Binary file not shown.

View file

@ -0,0 +1,25 @@
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\switch_toolbox\lib\directxtex\release\vc141.pdb
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\switch_toolbox\lib\directxtex\release\directxtexutil.obj
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\switch_toolbox\lib\directxtex\release\directxtexmipmaps.obj
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\switch_toolbox\lib\directxtex\release\directxteximage.obj
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\switch_toolbox\lib\directxtex\release\directxtexdds.obj
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\switch_toolbox\lib\directxtex\release\directxtexconvert.obj
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\switch_toolbox\lib\directxtex\release\directxtexcompress.obj
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\switch_toolbox\lib\directxtex\release\bc6hbc7.obj
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\switch_toolbox\lib\directxtex\release\bc4bc5.obj
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\switch_toolbox\lib\directxtex\release\bc.obj
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\switch_toolbox\lib\directxtex\release\wrapper.obj
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\switch_toolbox\lib\directxtex\release\.netframework,version=v4.6.assemblyattributes.obj
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\switch_toolbox\lib\directxtex\release\.netframework,version=v4.6.assemblyattributes.asm
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\release\directxtex.ipdb
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\release\directxtex.iobj
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\release\directxtex.dll
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\switch_toolbox\lib\directxtex\release\directxtex.tlog\cl.command.1.tlog
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\switch_toolbox\lib\directxtex\release\directxtex.tlog\cl.read.1.tlog
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\switch_toolbox\lib\directxtex\release\directxtex.tlog\cl.write.1.tlog
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\switch_toolbox\lib\directxtex\release\directxtex.tlog\directxtex.write.1u.tlog
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\switch_toolbox\lib\directxtex\release\directxtex.tlog\link.command.1.tlog
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\switch_toolbox\lib\directxtex\release\directxtex.tlog\link.read.1.tlog
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\switch_toolbox\lib\directxtex\release\directxtex.tlog\link.write.1.tlog
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\switch_toolbox\lib\directxtex\release\directxtex.tlog\metagen.read.1.tlog
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\switch_toolbox\lib\directxtex\release\directxtex.tlog\metagen.write.1.tlog

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,15 @@
 BC.cpp
BC4BC5.cpp
BC6HBC7.cpp
DirectXTexCompress.cpp
DirectXTexConvert.cpp
DirectXTexDDS.cpp
DirectXTexImage.cpp
DirectXTexMipmaps.cpp
DirectXTexUtil.cpp
wrapper.cpp
.NETFramework,Version=v4.6.AssemblyAttributes.cpp
Generating code
All 442 functions were compiled because no usable IPDB/IOBJ from previous compilation was found.
Finished generating code
DirectXTex.vcxproj -> C:\Users\Nathan\Documents\GitHub\Switch_Toolbox\Switch-Toolbox - Copy\Release\DirectXTex.dll

Binary file not shown.

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,891 @@
//-------------------------------------------------------------------------------------
// BC.h
//
// Block-compression (BC) functionality
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// http://go.microsoft.com/fwlink/?LinkId=248926
//-------------------------------------------------------------------------------------
#pragma once
#include <assert.h>
#include <directxmath.h>
#include <directxpackedvector.h>
namespace DirectX
{
//-------------------------------------------------------------------------------------
// Constants
//-------------------------------------------------------------------------------------
const uint16_t F16S_MASK = 0x8000; // f16 sign mask
const uint16_t F16EM_MASK = 0x7fff; // f16 exp & mantissa mask
const uint16_t F16MAX = 0x7bff; // MAXFLT bit pattern for XMHALF
#define SIGN_EXTEND(x,nb) ((((x)&(1<<((nb)-1)))?((~0)<<(nb)):0)|(x))
// Because these are used in SAL annotations, they need to remain macros rather than const values
#define NUM_PIXELS_PER_BLOCK 16
#define BC6H_MAX_REGIONS 2
#define BC6H_MAX_INDICES 16
#define BC7_MAX_REGIONS 3
#define BC7_MAX_INDICES 16
const size_t BC6H_NUM_CHANNELS = 3;
const size_t BC6H_MAX_SHAPES = 32;
const size_t BC7_NUM_CHANNELS = 4;
const size_t BC7_MAX_SHAPES = 64;
const int32_t BC67_WEIGHT_MAX = 64;
const uint32_t BC67_WEIGHT_SHIFT = 6;
const int32_t BC67_WEIGHT_ROUND = 32;
extern const int g_aWeights2[4];
extern const int g_aWeights3[8];
extern const int g_aWeights4[16];
enum BC_FLAGS
{
BC_FLAGS_NONE = 0x0,
BC_FLAGS_DITHER_RGB = 0x10000, // Enables dithering for RGB colors for BC1-3
BC_FLAGS_DITHER_A = 0x20000, // Enables dithering for Alpha channel for BC1-3
BC_FLAGS_UNIFORM = 0x40000, // By default, uses perceptual weighting for BC1-3; this flag makes it a uniform weighting
BC_FLAGS_USE_3SUBSETS = 0x80000,// By default, BC7 skips mode 0 & 2; this flag adds those modes back
};
//-------------------------------------------------------------------------------------
// Structures
//-------------------------------------------------------------------------------------
class HDRColorA;
class LDRColorA
{
public:
uint8_t r, g, b, a;
LDRColorA() DIRECTX_CTOR_DEFAULT
LDRColorA(uint8_t _r, uint8_t _g, uint8_t _b, uint8_t _a) : r(_r), g(_g), b(_b), a(_a) {}
const uint8_t& operator [] (_In_range_(0,3) size_t uElement) const
{
switch(uElement)
{
case 0: return r;
case 1: return g;
case 2: return b;
case 3: return a;
default: assert(false); return r;
}
}
uint8_t& operator [] (_In_range_(0,3) size_t uElement)
{
switch(uElement)
{
case 0: return r;
case 1: return g;
case 2: return b;
case 3: return a;
default: assert(false); return r;
}
}
LDRColorA operator = (_In_ const HDRColorA& c);
static void InterpolateRGB(_In_ const LDRColorA& c0, _In_ const LDRColorA& c1, _In_ size_t wc, _In_ _In_range_(2, 4) size_t wcprec, _Out_ LDRColorA& out)
{
const int* aWeights = nullptr;
switch(wcprec)
{
case 2: aWeights = g_aWeights2; assert( wc < 4 ); _Analysis_assume_( wc < 4 ); break;
case 3: aWeights = g_aWeights3; assert( wc < 8 ); _Analysis_assume_( wc < 8 ); break;
case 4: aWeights = g_aWeights4; assert( wc < 16 ); _Analysis_assume_( wc < 16 ); break;
default: assert(false); out.r = out.g = out.b = 0; return;
}
out.r = uint8_t((uint32_t(c0.r) * uint32_t(BC67_WEIGHT_MAX - aWeights[wc]) + uint32_t(c1.r) * uint32_t(aWeights[wc]) + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT);
out.g = uint8_t((uint32_t(c0.g) * uint32_t(BC67_WEIGHT_MAX - aWeights[wc]) + uint32_t(c1.g) * uint32_t(aWeights[wc]) + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT);
out.b = uint8_t((uint32_t(c0.b) * uint32_t(BC67_WEIGHT_MAX - aWeights[wc]) + uint32_t(c1.b) * uint32_t(aWeights[wc]) + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT);
}
static void InterpolateA(_In_ const LDRColorA& c0, _In_ const LDRColorA& c1, _In_ size_t wa, _In_range_(2, 4) _In_ size_t waprec, _Out_ LDRColorA& out)
{
const int* aWeights = nullptr;
switch(waprec)
{
case 2: aWeights = g_aWeights2; assert( wa < 4 ); _Analysis_assume_( wa < 4 ); break;
case 3: aWeights = g_aWeights3; assert( wa < 8 ); _Analysis_assume_( wa < 8 ); break;
case 4: aWeights = g_aWeights4; assert( wa < 16 ); _Analysis_assume_( wa < 16 ); break;
default: assert(false); out.a = 0; return;
}
out.a = uint8_t((uint32_t(c0.a) * uint32_t(BC67_WEIGHT_MAX - aWeights[wa]) + uint32_t(c1.a) * uint32_t(aWeights[wa]) + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT);
}
static void Interpolate(_In_ const LDRColorA& c0, _In_ const LDRColorA& c1, _In_ size_t wc, _In_ size_t wa, _In_ _In_range_(2, 4) size_t wcprec, _In_ _In_range_(2, 4) size_t waprec, _Out_ LDRColorA& out)
{
InterpolateRGB(c0, c1, wc, wcprec, out);
InterpolateA(c0, c1, wa, waprec, out);
}
};
static_assert( sizeof(LDRColorA) == 4, "Unexpected packing");
class HDRColorA
{
public:
float r, g, b, a;
public:
HDRColorA() DIRECTX_CTOR_DEFAULT
HDRColorA(float _r, float _g, float _b, float _a) : r(_r), g(_g), b(_b), a(_a) {}
HDRColorA(const HDRColorA& c) : r(c.r), g(c.g), b(c.b), a(c.a) {}
HDRColorA(const LDRColorA& c)
{
r = float(c.r) * (1.0f/255.0f);
g = float(c.g) * (1.0f/255.0f);
b = float(c.b) * (1.0f/255.0f);
a = float(c.a) * (1.0f/255.0f);
}
// binary operators
HDRColorA operator + ( _In_ const HDRColorA& c ) const
{
return HDRColorA(r + c.r, g + c.g, b + c.b, a + c.a);
}
HDRColorA operator - ( _In_ const HDRColorA& c ) const
{
return HDRColorA(r - c.r, g - c.g, b - c.b, a - c.a);
}
HDRColorA operator * ( _In_ float f ) const
{
return HDRColorA(r * f, g * f, b * f, a * f);
}
HDRColorA operator / ( _In_ float f ) const
{
float fInv = 1.0f / f;
return HDRColorA(r * fInv, g * fInv, b * fInv, a * fInv);
}
float operator * ( _In_ const HDRColorA& c ) const
{
return r * c.r + g * c.g + b * c.b + a * c.a;
}
// assignment operators
HDRColorA& operator += ( _In_ const HDRColorA& c )
{
r += c.r;
g += c.g;
b += c.b;
a += c.a;
return *this;
}
HDRColorA& operator -= ( _In_ const HDRColorA& c )
{
r -= c.r;
g -= c.g;
b -= c.b;
a -= c.a;
return *this;
}
HDRColorA& operator *= ( _In_ float f )
{
r *= f;
g *= f;
b *= f;
a *= f;
return *this;
}
HDRColorA& operator /= ( _In_ float f )
{
float fInv = 1.0f / f;
r *= fInv;
g *= fInv;
b *= fInv;
a *= fInv;
return *this;
}
HDRColorA& operator = (_In_ const LDRColorA& c)
{
r = (float) c.r;
g = (float) c.g;
b = (float) c.b;
a = (float) c.a;
return *this;
}
HDRColorA& Clamp(_In_ float fMin, _In_ float fMax)
{
r = std::min<float>(fMax, std::max<float>(fMin, r));
g = std::min<float>(fMax, std::max<float>(fMin, g));
b = std::min<float>(fMax, std::max<float>(fMin, b));
a = std::min<float>(fMax, std::max<float>(fMin, a));
return *this;
}
LDRColorA ToLDRColorA() const
{
return LDRColorA((uint8_t) (r + 0.01f), (uint8_t) (g + 0.01f), (uint8_t) (b + 0.01f), (uint8_t) (a + 0.01f));
}
};
inline LDRColorA LDRColorA::operator = (_In_ const HDRColorA& c)
{
LDRColorA ret;
HDRColorA tmp(c);
tmp = tmp.Clamp(0.0f, 1.0f) * 255.0f;
ret.r = uint8_t(tmp.r + 0.001f);
ret.g = uint8_t(tmp.g + 0.001f);
ret.b = uint8_t(tmp.b + 0.001f);
ret.a = uint8_t(tmp.a + 0.001f);
return ret;
}
struct LDREndPntPair
{
LDRColorA A;
LDRColorA B;
};
struct HDREndPntPair
{
HDRColorA A;
HDRColorA B;
};
inline HDRColorA* HDRColorALerp(_Out_ HDRColorA *pOut, _In_ const HDRColorA *pC1, _In_ const HDRColorA *pC2, _In_ float s)
{
pOut->r = pC1->r + s * (pC2->r - pC1->r);
pOut->g = pC1->g + s * (pC2->g - pC1->g);
pOut->b = pC1->b + s * (pC2->b - pC1->b);
pOut->a = pC1->a + s * (pC2->a - pC1->a);
return pOut;
}
#pragma pack(push,1)
// BC1/DXT1 compression (4 bits per texel)
struct D3DX_BC1
{
uint16_t rgb[2]; // 565 colors
uint32_t bitmap; // 2bpp rgb bitmap
};
// BC2/DXT2/3 compression (8 bits per texel)
struct D3DX_BC2
{
uint32_t bitmap[2]; // 4bpp alpha bitmap
D3DX_BC1 bc1; // BC1 rgb data
};
// BC3/DXT4/5 compression (8 bits per texel)
struct D3DX_BC3
{
uint8_t alpha[2]; // alpha values
uint8_t bitmap[6]; // 3bpp alpha bitmap
D3DX_BC1 bc1; // BC1 rgb data
};
#pragma pack(pop)
class INTColor
{
public:
int r, g, b;
int pad;
public:
INTColor() DIRECTX_CTOR_DEFAULT
INTColor(int nr, int ng, int nb) {r = nr; g = ng; b = nb;}
INTColor(const INTColor& c) {r = c.r; g = c.g; b = c.b;}
INTColor operator - ( _In_ const INTColor& c ) const
{
return INTColor(r - c.r, g - c.g, b - c.b);
}
INTColor& operator += ( _In_ const INTColor& c )
{
r += c.r;
g += c.g;
b += c.b;
return *this;
}
INTColor& operator -= ( _In_ const INTColor& c )
{
r -= c.r;
g -= c.g;
b -= c.b;
return *this;
}
INTColor& operator &= ( _In_ const INTColor& c )
{
r &= c.r;
g &= c.g;
b &= c.b;
return *this;
}
int& operator [] ( _In_ uint8_t i )
{
assert(i < sizeof(INTColor) / sizeof(int));
_Analysis_assume_(i < sizeof(INTColor) / sizeof(int));
return ((int*) this)[i];
}
void Set(_In_ const HDRColorA& c, _In_ bool bSigned)
{
PackedVector::XMHALF4 aF16;
XMVECTOR v = XMLoadFloat4( (const XMFLOAT4*)& c );
XMStoreHalf4( &aF16, v );
r = F16ToINT(aF16.x, bSigned);
g = F16ToINT(aF16.y, bSigned);
b = F16ToINT(aF16.z, bSigned);
}
INTColor& Clamp(_In_ int iMin, _In_ int iMax)
{
r = std::min<int>(iMax, std::max<int>(iMin, r));
g = std::min<int>(iMax, std::max<int>(iMin, g));
b = std::min<int>(iMax, std::max<int>(iMin, b));
return *this;
}
INTColor& SignExtend(_In_ const LDRColorA& Prec)
{
r = SIGN_EXTEND(r, Prec.r);
g = SIGN_EXTEND(g, Prec.g);
b = SIGN_EXTEND(b, Prec.b);
return *this;
}
void ToF16(_Out_writes_(3) PackedVector::HALF aF16[3], _In_ bool bSigned) const
{
aF16[0] = INT2F16(r, bSigned);
aF16[1] = INT2F16(g, bSigned);
aF16[2] = INT2F16(b, bSigned);
}
private:
static int F16ToINT(_In_ const PackedVector::HALF& f, _In_ bool bSigned)
{
uint16_t input = *((const uint16_t*) &f);
int out, s;
if(bSigned)
{
s = input & F16S_MASK;
input &= F16EM_MASK;
if(input > F16MAX) out = F16MAX;
else out = input;
out = s ? -out : out;
}
else
{
if(input & F16S_MASK) out = 0;
else out = input;
}
return out;
}
static PackedVector::HALF INT2F16(_In_ int input, _In_ bool bSigned)
{
PackedVector::HALF h;
uint16_t out;
if(bSigned)
{
int s = 0;
if(input < 0)
{
s = F16S_MASK;
input = -input;
}
out = uint16_t(s | input);
}
else
{
assert(input >= 0 && input <= F16MAX);
out = (uint16_t) input;
}
*((uint16_t*) &h) = out;
return h;
}
};
static_assert( sizeof(INTColor) == 16, "Unexpected packing");
struct INTEndPntPair
{
INTColor A;
INTColor B;
};
template< size_t SizeInBytes >
class CBits
{
public:
uint8_t GetBit(_Inout_ size_t& uStartBit) const
{
assert(uStartBit < 128);
_Analysis_assume_(uStartBit < 128);
size_t uIndex = uStartBit >> 3;
uint8_t ret = (m_uBits[uIndex] >> (uStartBit - (uIndex << 3))) & 0x01;
uStartBit++;
return ret;
}
uint8_t GetBits(_Inout_ size_t& uStartBit, _In_ size_t uNumBits) const
{
if(uNumBits == 0) return 0;
assert(uStartBit + uNumBits <= 128 && uNumBits <= 8);
_Analysis_assume_(uStartBit + uNumBits <= 128 && uNumBits <= 8);
uint8_t ret;
size_t uIndex = uStartBit >> 3;
size_t uBase = uStartBit - (uIndex << 3);
if(uBase + uNumBits > 8)
{
size_t uFirstIndexBits = 8 - uBase;
size_t uNextIndexBits = uNumBits - uFirstIndexBits;
ret = (m_uBits[uIndex] >> uBase) | ((m_uBits[uIndex+1] & ((1 << uNextIndexBits) - 1)) << uFirstIndexBits);
}
else
{
ret = (m_uBits[uIndex] >> uBase) & ((1 << uNumBits) - 1);
}
assert(ret < (1 << uNumBits));
uStartBit += uNumBits;
return ret;
}
void SetBit(_Inout_ size_t& uStartBit, _In_ uint8_t uValue)
{
assert(uStartBit < 128 && uValue < 2);
_Analysis_assume_(uStartBit < 128 && uValue < 2);
size_t uIndex = uStartBit >> 3;
size_t uBase = uStartBit - (uIndex << 3);
m_uBits[uIndex] &= ~(1 << uBase);
m_uBits[uIndex] |= uValue << uBase;
uStartBit++;
}
void SetBits(_Inout_ size_t& uStartBit, _In_ size_t uNumBits, _In_ uint8_t uValue)
{
if(uNumBits == 0)
return;
assert(uStartBit + uNumBits <= 128 && uNumBits <= 8);
_Analysis_assume_(uStartBit + uNumBits <= 128 && uNumBits <= 8);
assert(uValue < (1 << uNumBits));
size_t uIndex = uStartBit >> 3;
size_t uBase = uStartBit - (uIndex << 3);
if(uBase + uNumBits > 8)
{
size_t uFirstIndexBits = 8 - uBase;
size_t uNextIndexBits = uNumBits - uFirstIndexBits;
m_uBits[uIndex] &= ~(((1 << uFirstIndexBits) - 1) << uBase);
m_uBits[uIndex] |= uValue << uBase;
m_uBits[uIndex+1] &= ~((1 << uNextIndexBits) - 1);
m_uBits[uIndex+1] |= uValue >> uFirstIndexBits;
}
else
{
m_uBits[uIndex] &= ~(((1 << uNumBits) - 1) << uBase);
m_uBits[uIndex] |= uValue << uBase;
}
uStartBit += uNumBits;
}
private:
uint8_t m_uBits[ SizeInBytes ];
};
// BC6H compression (16 bits per texel)
class D3DX_BC6H : private CBits< 16 >
{
public:
void Decode(_In_ bool bSigned, _Out_writes_(NUM_PIXELS_PER_BLOCK) HDRColorA* pOut) const;
void Encode(_In_ bool bSigned, _In_reads_(NUM_PIXELS_PER_BLOCK) const HDRColorA* const pIn);
private:
#pragma warning(push)
#pragma warning(disable : 4480)
enum EField : uint8_t
{
NA, // N/A
M, // Mode
D, // Shape
RW,
RX,
RY,
RZ,
GW,
GX,
GY,
GZ,
BW,
BX,
BY,
BZ,
};
#pragma warning(pop)
struct ModeDescriptor
{
EField m_eField;
uint8_t m_uBit;
};
struct ModeInfo
{
uint8_t uMode;
uint8_t uPartitions;
bool bTransformed;
uint8_t uIndexPrec;
LDRColorA RGBAPrec[BC6H_MAX_REGIONS][2];
};
#pragma warning(push)
#pragma warning(disable : 4512)
struct EncodeParams
{
float fBestErr;
const bool bSigned;
uint8_t uMode;
uint8_t uShape;
const HDRColorA* const aHDRPixels;
INTEndPntPair aUnqEndPts[BC6H_MAX_SHAPES][BC6H_MAX_REGIONS];
INTColor aIPixels[NUM_PIXELS_PER_BLOCK];
EncodeParams(const HDRColorA* const aOriginal, bool bSignedFormat) :
aHDRPixels(aOriginal), fBestErr(FLT_MAX), bSigned(bSignedFormat)
{
for(size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
aIPixels[i].Set(aOriginal[i], bSigned);
}
}
};
#pragma warning(pop)
static int Quantize(_In_ int iValue, _In_ int prec, _In_ bool bSigned);
static int Unquantize(_In_ int comp, _In_ uint8_t uBitsPerComp, _In_ bool bSigned);
static int FinishUnquantize(_In_ int comp, _In_ bool bSigned);
static bool EndPointsFit(_In_ const EncodeParams* pEP, _In_reads_(BC6H_MAX_REGIONS) const INTEndPntPair aEndPts[]);
void GeneratePaletteQuantized(_In_ const EncodeParams* pEP, _In_ const INTEndPntPair& endPts,
_Out_writes_(BC6H_MAX_INDICES) INTColor aPalette[]) const;
float MapColorsQuantized(_In_ const EncodeParams* pEP, _In_reads_(np) const INTColor aColors[], _In_ size_t np, _In_ const INTEndPntPair &endPts) const;
float PerturbOne(_In_ const EncodeParams* pEP, _In_reads_(np) const INTColor aColors[], _In_ size_t np, _In_ uint8_t ch,
_In_ const INTEndPntPair& oldEndPts, _Out_ INTEndPntPair& newEndPts, _In_ float fOldErr, _In_ int do_b) const;
void OptimizeOne(_In_ const EncodeParams* pEP, _In_reads_(np) const INTColor aColors[], _In_ size_t np, _In_ float aOrgErr,
_In_ const INTEndPntPair &aOrgEndPts, _Out_ INTEndPntPair &aOptEndPts) const;
void OptimizeEndPoints(_In_ const EncodeParams* pEP, _In_reads_(BC6H_MAX_REGIONS) const float aOrgErr[],
_In_reads_(BC6H_MAX_REGIONS) const INTEndPntPair aOrgEndPts[],
_Out_writes_all_(BC6H_MAX_REGIONS) INTEndPntPair aOptEndPts[]) const;
static void SwapIndices(_In_ const EncodeParams* pEP, _Inout_updates_all_(BC6H_MAX_REGIONS) INTEndPntPair aEndPts[],
_In_reads_(NUM_PIXELS_PER_BLOCK) size_t aIndices[]);
void AssignIndices(_In_ const EncodeParams* pEP, _In_reads_(BC6H_MAX_REGIONS) const INTEndPntPair aEndPts[],
_Out_writes_(NUM_PIXELS_PER_BLOCK) size_t aIndices[],
_Out_writes_(BC6H_MAX_REGIONS) float aTotErr[]) const;
void QuantizeEndPts(_In_ const EncodeParams* pEP, _Out_writes_(BC6H_MAX_REGIONS) INTEndPntPair* qQntEndPts) const;
void EmitBlock(_In_ const EncodeParams* pEP, _In_reads_(BC6H_MAX_REGIONS) const INTEndPntPair aEndPts[],
_In_reads_(NUM_PIXELS_PER_BLOCK) const size_t aIndices[]);
void Refine(_Inout_ EncodeParams* pEP);
static void GeneratePaletteUnquantized(_In_ const EncodeParams* pEP, _In_ size_t uRegion, _Out_writes_(BC6H_MAX_INDICES) INTColor aPalette[]);
float MapColors(_In_ const EncodeParams* pEP, _In_ size_t uRegion, _In_ size_t np, _In_reads_(np) const size_t* auIndex) const;
float RoughMSE(_Inout_ EncodeParams* pEP) const;
private:
const static ModeDescriptor ms_aDesc[][82];
const static ModeInfo ms_aInfo[];
const static int ms_aModeToInfo[];
};
// BC67 compression (16b bits per texel)
class D3DX_BC7 : private CBits< 16 >
{
public:
void Decode(_Out_writes_(NUM_PIXELS_PER_BLOCK) HDRColorA* pOut) const;
void Encode(bool skip3subsets, _In_reads_(NUM_PIXELS_PER_BLOCK) const HDRColorA* const pIn);
private:
struct ModeInfo
{
uint8_t uPartitions;
uint8_t uPartitionBits;
uint8_t uPBits;
uint8_t uRotationBits;
uint8_t uIndexModeBits;
uint8_t uIndexPrec;
uint8_t uIndexPrec2;
LDRColorA RGBAPrec;
LDRColorA RGBAPrecWithP;
};
#pragma warning(push)
#pragma warning(disable : 4512)
struct EncodeParams
{
uint8_t uMode;
LDREndPntPair aEndPts[BC7_MAX_SHAPES][BC7_MAX_REGIONS];
LDRColorA aLDRPixels[NUM_PIXELS_PER_BLOCK];
const HDRColorA* const aHDRPixels;
EncodeParams(const HDRColorA* const aOriginal) : aHDRPixels(aOriginal) {}
};
#pragma warning(pop)
static uint8_t Quantize(_In_ uint8_t comp, _In_ uint8_t uPrec)
{
assert(0 < uPrec && uPrec <= 8);
uint8_t rnd = (uint8_t) std::min<uint16_t>(255, uint16_t(comp) + (1 << (7 - uPrec)));
return rnd >> (8 - uPrec);
}
static LDRColorA Quantize(_In_ const LDRColorA& c, _In_ const LDRColorA& RGBAPrec)
{
LDRColorA q;
q.r = Quantize(c.r, RGBAPrec.r);
q.g = Quantize(c.g, RGBAPrec.g);
q.b = Quantize(c.b, RGBAPrec.b);
if(RGBAPrec.a)
q.a = Quantize(c.a, RGBAPrec.a);
else
q.a = 255;
return q;
}
static uint8_t Unquantize(_In_ uint8_t comp, _In_ size_t uPrec)
{
assert(0 < uPrec && uPrec <= 8);
comp = comp << (8 - uPrec);
return comp | (comp >> uPrec);
}
static LDRColorA Unquantize(_In_ const LDRColorA& c, _In_ const LDRColorA& RGBAPrec)
{
LDRColorA q;
q.r = Unquantize(c.r, RGBAPrec.r);
q.g = Unquantize(c.g, RGBAPrec.g);
q.b = Unquantize(c.b, RGBAPrec.b);
q.a = RGBAPrec.a > 0 ? Unquantize(c.a, RGBAPrec.a) : 255;
return q;
}
void GeneratePaletteQuantized(_In_ const EncodeParams* pEP, _In_ size_t uIndexMode, _In_ const LDREndPntPair& endpts,
_Out_writes_(BC7_MAX_INDICES) LDRColorA aPalette[]) const;
float PerturbOne(_In_ const EncodeParams* pEP, _In_reads_(np) const LDRColorA colors[], _In_ size_t np, _In_ size_t uIndexMode,
_In_ size_t ch, _In_ const LDREndPntPair &old_endpts,
_Out_ LDREndPntPair &new_endpts, _In_ float old_err, _In_ uint8_t do_b) const;
void Exhaustive(_In_ const EncodeParams* pEP, _In_reads_(np) const LDRColorA aColors[], _In_ size_t np, _In_ size_t uIndexMode,
_In_ size_t ch, _Inout_ float& fOrgErr, _Inout_ LDREndPntPair& optEndPt) const;
void OptimizeOne(_In_ const EncodeParams* pEP, _In_reads_(np) const LDRColorA colors[], _In_ size_t np, _In_ size_t uIndexMode,
_In_ float orig_err, _In_ const LDREndPntPair &orig_endpts, _Out_ LDREndPntPair &opt_endpts) const;
void OptimizeEndPoints(_In_ const EncodeParams* pEP, _In_ size_t uShape, _In_ size_t uIndexMode,
_In_reads_(BC7_MAX_REGIONS) const float orig_err[],
_In_reads_(BC7_MAX_REGIONS) const LDREndPntPair orig_endpts[],
_Out_writes_(BC7_MAX_REGIONS) LDREndPntPair opt_endpts[]) const;
void AssignIndices(_In_ const EncodeParams* pEP, _In_ size_t uShape, _In_ size_t uIndexMode,
_In_reads_(BC7_MAX_REGIONS) LDREndPntPair endpts[],
_Out_writes_(NUM_PIXELS_PER_BLOCK) size_t aIndices[], _Out_writes_(NUM_PIXELS_PER_BLOCK) size_t aIndices2[],
_Out_writes_(BC7_MAX_REGIONS) float afTotErr[]) const;
void EmitBlock(_In_ const EncodeParams* pEP, _In_ size_t uShape, _In_ size_t uRotation, _In_ size_t uIndexMode,
_In_reads_(BC7_MAX_REGIONS) const LDREndPntPair aEndPts[],
_In_reads_(NUM_PIXELS_PER_BLOCK) const size_t aIndex[],
_In_reads_(NUM_PIXELS_PER_BLOCK) const size_t aIndex2[]);
float Refine(_In_ const EncodeParams* pEP, _In_ size_t uShape, _In_ size_t uRotation, _In_ size_t uIndexMode);
float MapColors(_In_ const EncodeParams* pEP, _In_reads_(np) const LDRColorA aColors[], _In_ size_t np, _In_ size_t uIndexMode,
_In_ const LDREndPntPair& endPts, _In_ float fMinErr) const;
static float RoughMSE(_Inout_ EncodeParams* pEP, _In_ size_t uShape, _In_ size_t uIndexMode);
private:
const static ModeInfo ms_aInfo[];
};
//-------------------------------------------------------------------------------------
#pragma warning(push)
#pragma warning(disable : 4127)
template <bool bRange> void OptimizeAlpha(float *pX, float *pY, const float *pPoints, size_t cSteps)
{
static const float pC6[] = { 5.0f/5.0f, 4.0f/5.0f, 3.0f/5.0f, 2.0f/5.0f, 1.0f/5.0f, 0.0f/5.0f };
static const float pD6[] = { 0.0f/5.0f, 1.0f/5.0f, 2.0f/5.0f, 3.0f/5.0f, 4.0f/5.0f, 5.0f/5.0f };
static const float pC8[] = { 7.0f/7.0f, 6.0f/7.0f, 5.0f/7.0f, 4.0f/7.0f, 3.0f/7.0f, 2.0f/7.0f, 1.0f/7.0f, 0.0f/7.0f };
static const float pD8[] = { 0.0f/7.0f, 1.0f/7.0f, 2.0f/7.0f, 3.0f/7.0f, 4.0f/7.0f, 5.0f/7.0f, 6.0f/7.0f, 7.0f/7.0f };
const float *pC = (6 == cSteps) ? pC6 : pC8;
const float *pD = (6 == cSteps) ? pD6 : pD8;
float MAX_VALUE = 1.0f;
float MIN_VALUE;
if (bRange)
{
MIN_VALUE = -1.0f;
}
else
{
MIN_VALUE = 0.0f;
}
// Find Min and Max points, as starting point
float fX = MAX_VALUE;
float fY = MIN_VALUE;
if(8 == cSteps)
{
for(size_t iPoint = 0; iPoint < NUM_PIXELS_PER_BLOCK; iPoint++)
{
if(pPoints[iPoint] < fX)
fX = pPoints[iPoint];
if(pPoints[iPoint] > fY)
fY = pPoints[iPoint];
}
}
else
{
for(size_t iPoint = 0; iPoint < NUM_PIXELS_PER_BLOCK; iPoint++)
{
if(pPoints[iPoint] < fX && pPoints[iPoint] > MIN_VALUE)
fX = pPoints[iPoint];
if(pPoints[iPoint] > fY && pPoints[iPoint] < MAX_VALUE)
fY = pPoints[iPoint];
}
if (fX == fY)
{
fY = MAX_VALUE;
}
}
// Use Newton's Method to find local minima of sum-of-squares error.
float fSteps = (float) (cSteps - 1);
for(size_t iIteration = 0; iIteration < 8; iIteration++)
{
float fScale;
if((fY - fX) < (1.0f / 256.0f))
break;
fScale = fSteps / (fY - fX);
// Calculate new steps
float pSteps[8];
for(size_t iStep = 0; iStep < cSteps; iStep++)
pSteps[iStep] = pC[iStep] * fX + pD[iStep] * fY;
if(6 == cSteps)
{
pSteps[6] = MIN_VALUE;
pSteps[7] = MAX_VALUE;
}
// Evaluate function, and derivatives
float dX = 0.0f;
float dY = 0.0f;
float d2X = 0.0f;
float d2Y = 0.0f;
for(size_t iPoint = 0; iPoint < NUM_PIXELS_PER_BLOCK; iPoint++)
{
float fDot = (pPoints[iPoint] - fX) * fScale;
size_t iStep;
if(fDot <= 0.0f)
iStep = ((6 == cSteps) && (pPoints[iPoint] <= fX * 0.5f)) ? 6 : 0;
else if(fDot >= fSteps)
iStep = ((6 == cSteps) && (pPoints[iPoint] >= (fY + 1.0f) * 0.5f)) ? 7 : (cSteps - 1);
else
iStep = static_cast<int32_t>(fDot + 0.5f);
if(iStep < cSteps)
{
// D3DX had this computation backwards (pPoints[iPoint] - pSteps[iStep])
// this fix improves RMS of the alpha component
float fDiff = pSteps[iStep] - pPoints[iPoint];
dX += pC[iStep] * fDiff;
d2X += pC[iStep] * pC[iStep];
dY += pD[iStep] * fDiff;
d2Y += pD[iStep] * pD[iStep];
}
}
// Move endpoints
if(d2X > 0.0f)
fX -= dX / d2X;
if(d2Y > 0.0f)
fY -= dY / d2Y;
if(fX > fY)
{
float f = fX; fX = fY; fY = f;
}
if((dX * dX < (1.0f / 64.0f)) && (dY * dY < (1.0f / 64.0f)))
break;
}
*pX = (fX < MIN_VALUE) ? MIN_VALUE : (fX > MAX_VALUE) ? MAX_VALUE : fX;
*pY = (fY < MIN_VALUE) ? MIN_VALUE : (fY > MAX_VALUE) ? MAX_VALUE : fY;
}
#pragma warning(pop)
//-------------------------------------------------------------------------------------
// Functions
//-------------------------------------------------------------------------------------
typedef void (*BC_DECODE)(XMVECTOR *pColor, const uint8_t *pBC);
typedef void (*BC_ENCODE)(uint8_t *pDXT, const XMVECTOR *pColor, DWORD flags);
void D3DXDecodeBC1(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(8) const uint8_t *pBC);
void D3DXDecodeBC2(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(16) const uint8_t *pBC);
void D3DXDecodeBC3(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(16) const uint8_t *pBC);
void D3DXDecodeBC4U(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(8) const uint8_t *pBC);
void D3DXDecodeBC4S(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(8) const uint8_t *pBC);
void D3DXDecodeBC5U(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(16) const uint8_t *pBC);
void D3DXDecodeBC5S(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(16) const uint8_t *pBC);
void D3DXDecodeBC6HU(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(16) const uint8_t *pBC);
void D3DXDecodeBC6HS(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(16) const uint8_t *pBC);
void D3DXDecodeBC7(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(16) const uint8_t *pBC);
void D3DXEncodeBC1(_Out_writes_(8) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ float alphaRef, _In_ DWORD flags);
// BC1 requires one additional parameter, so it doesn't match signature of BC_ENCODE above
void D3DXEncodeBC2(_Out_writes_(16) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags);
void D3DXEncodeBC3(_Out_writes_(16) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags);
void D3DXEncodeBC4U(_Out_writes_(8) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags);
void D3DXEncodeBC4S(_Out_writes_(8) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags);
void D3DXEncodeBC5U(_Out_writes_(16) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags);
void D3DXEncodeBC5S(_Out_writes_(16) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags);
void D3DXEncodeBC6HU(_Out_writes_(16) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags);
void D3DXEncodeBC6HS(_Out_writes_(16) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags);
void D3DXEncodeBC7(_Out_writes_(16) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags);
}; // namespace

View file

@ -0,0 +1,548 @@
//-------------------------------------------------------------------------------------
// BC4BC5.cpp
//
// Block-compression (BC) functionality for BC4 and BC5 (DirectX 10 texture compression)
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// http://go.microsoft.com/fwlink/?LinkId=248926
//-------------------------------------------------------------------------------------
#include "directxtexp.h"
#include "BC.h"
namespace DirectX
{
//------------------------------------------------------------------------------------
// Constants
//------------------------------------------------------------------------------------
// Because these are used in SAL annotations, they need to remain macros rather than const values
#define BLOCK_LEN 4
// length of each block in texel
#define BLOCK_SIZE (BLOCK_LEN * BLOCK_LEN)
// total texels in a 4x4 block.
//------------------------------------------------------------------------------------
// Structures
//-------------------------------------------------------------------------------------
#pragma warning(push)
#pragma warning(disable : 4201)
// BC4U/BC5U
struct BC4_UNORM
{
float R(size_t uOffset) const
{
size_t uIndex = GetIndex(uOffset);
return DecodeFromIndex(uIndex);
}
float DecodeFromIndex(size_t uIndex) const
{
if (uIndex == 0)
return red_0 / 255.0f;
if (uIndex == 1)
return red_1 / 255.0f;
float fred_0 = red_0 / 255.0f;
float fred_1 = red_1 / 255.0f;
if (red_0 > red_1)
{
uIndex -= 1;
return (fred_0 * (7-uIndex) + fred_1 * uIndex) / 7.0f;
}
else
{
if (uIndex == 6)
return 0.0f;
if (uIndex == 7)
return 1.0f;
uIndex -= 1;
return (fred_0 * (5-uIndex) + fred_1 * uIndex) / 5.0f;
}
}
size_t GetIndex(size_t uOffset) const
{
return (size_t) ((data >> (3*uOffset + 16)) & 0x07);
}
void SetIndex(size_t uOffset, size_t uIndex)
{
data &= ~((uint64_t) 0x07 << (3*uOffset + 16));
data |= ((uint64_t) uIndex << (3*uOffset + 16));
}
union
{
struct
{
uint8_t red_0;
uint8_t red_1;
uint8_t indices[6];
};
uint64_t data;
};
};
// BC4S/BC5S
struct BC4_SNORM
{
float R(size_t uOffset) const
{
size_t uIndex = GetIndex(uOffset);
return DecodeFromIndex(uIndex);
}
float DecodeFromIndex(size_t uIndex) const
{
int8_t sred_0 = (red_0 == -128)? -127 : red_0;
int8_t sred_1 = (red_1 == -128)? -127 : red_1;
if (uIndex == 0)
return sred_0 / 127.0f;
if (uIndex == 1)
return sred_1 / 127.0f;
float fred_0 = sred_0 / 127.0f;
float fred_1 = sred_1 / 127.0f;
if (red_0 > red_1)
{
uIndex -= 1;
return (fred_0 * (7-uIndex) + fred_1 * uIndex) / 7.0f;
}
else
{
if (uIndex == 6)
return -1.0f;
if (uIndex == 7)
return 1.0f;
uIndex -= 1;
return (fred_0 * (5-uIndex) + fred_1 * uIndex) / 5.0f;
}
}
size_t GetIndex(size_t uOffset) const
{
return (size_t) ((data >> (3*uOffset + 16)) & 0x07);
}
void SetIndex(size_t uOffset, size_t uIndex)
{
data &= ~((uint64_t) 0x07 << (3*uOffset + 16));
data |= ((uint64_t) uIndex << (3*uOffset + 16));
}
union
{
struct
{
int8_t red_0;
int8_t red_1;
uint8_t indices[6];
};
uint64_t data;
};
};
#pragma warning(pop)
//-------------------------------------------------------------------------------------
// Convert a floating point value to an 8-bit SNORM
//-------------------------------------------------------------------------------------
static void inline FloatToSNorm( _In_ float fVal, _Out_ int8_t *piSNorm )
{
const uint32_t dwMostNeg = ( 1 << ( 8 * sizeof( int8_t ) - 1 ) );
if( _isnan( fVal ) )
fVal = 0;
else
if( fVal > 1 )
fVal = 1; // Clamp to 1
else
if( fVal < -1 )
fVal = -1; // Clamp to -1
fVal = fVal * (int8_t) ( dwMostNeg - 1 );
if( fVal >= 0 )
fVal += .5f;
else
fVal -= .5f;
*piSNorm = (int8_t) (fVal);
}
//------------------------------------------------------------------------------
static void FindEndPointsBC4U( _In_reads_(BLOCK_SIZE) const float theTexelsU[], _Out_ uint8_t &endpointU_0, _Out_ uint8_t &endpointU_1)
{
// The boundary of codec for signed/unsigned format
float MIN_NORM;
float MAX_NORM = 1.0f;
int8_t iStart, iEnd;
size_t i;
MIN_NORM = 0.0f;
// Find max/min of input texels
float fBlockMax = theTexelsU[0];
float fBlockMin = theTexelsU[0];
for (i = 0; i < BLOCK_SIZE; ++i)
{
if (theTexelsU[i]<fBlockMin)
{
fBlockMin = theTexelsU[i];
}
else if (theTexelsU[i]>fBlockMax)
{
fBlockMax = theTexelsU[i];
}
}
// If there are boundary values in input texels, Should use 4 block-codec to guarantee
// the exact code of the boundary values.
bool bUsing4BlockCodec = ( MIN_NORM == fBlockMin || MAX_NORM == fBlockMax );
// Using Optimize
float fStart, fEnd;
if (!bUsing4BlockCodec)
{
OptimizeAlpha<false>(&fStart, &fEnd, theTexelsU, 8);
iStart = (uint8_t) (fStart * 255.0f);
iEnd = (uint8_t) (fEnd * 255.0f);
endpointU_0 = iEnd;
endpointU_1 = iStart;
}
else
{
OptimizeAlpha<false>(&fStart, &fEnd, theTexelsU, 6);
iStart = (uint8_t) (fStart * 255.0f);
iEnd = (uint8_t) (fEnd * 255.0f);
endpointU_1 = iEnd;
endpointU_0 = iStart;
}
}
static void FindEndPointsBC4S(_In_reads_(BLOCK_SIZE) const float theTexelsU[], _Out_ int8_t &endpointU_0, _Out_ int8_t &endpointU_1)
{
// The boundary of codec for signed/unsigned format
float MIN_NORM;
float MAX_NORM = 1.0f;
int8_t iStart, iEnd;
size_t i;
MIN_NORM = -1.0f;
// Find max/min of input texels
float fBlockMax = theTexelsU[0];
float fBlockMin = theTexelsU[0];
for (i = 0; i < BLOCK_SIZE; ++i)
{
if (theTexelsU[i]<fBlockMin)
{
fBlockMin = theTexelsU[i];
}
else if (theTexelsU[i]>fBlockMax)
{
fBlockMax = theTexelsU[i];
}
}
// If there are boundary values in input texels, Should use 4 block-codec to guarantee
// the exact code of the boundary values.
bool bUsing4BlockCodec = ( MIN_NORM == fBlockMin || MAX_NORM == fBlockMax );
// Using Optimize
float fStart, fEnd;
if (!bUsing4BlockCodec)
{
OptimizeAlpha<true>(&fStart, &fEnd, theTexelsU, 8);
FloatToSNorm(fStart, &iStart);
FloatToSNorm(fEnd, &iEnd);
endpointU_0 = iEnd;
endpointU_1 = iStart;
}
else
{
OptimizeAlpha<true>(&fStart, &fEnd, theTexelsU, 6);
FloatToSNorm(fStart, &iStart);
FloatToSNorm(fEnd, &iEnd);
endpointU_1 = iEnd;
endpointU_0 = iStart;
}
}
//------------------------------------------------------------------------------
static inline void FindEndPointsBC5U( _In_reads_(BLOCK_SIZE) const float theTexelsU[], _In_reads_(BLOCK_SIZE) const float theTexelsV[],
_Out_ uint8_t &endpointU_0, _Out_ uint8_t &endpointU_1, _Out_ uint8_t &endpointV_0, _Out_ uint8_t &endpointV_1)
{
//Encoding the U and V channel by BC4 codec separately.
FindEndPointsBC4U( theTexelsU, endpointU_0, endpointU_1);
FindEndPointsBC4U( theTexelsV, endpointV_0, endpointV_1);
}
static inline void FindEndPointsBC5S( _In_reads_(BLOCK_SIZE) const float theTexelsU[], _In_reads_(BLOCK_SIZE) const float theTexelsV[],
_Out_ int8_t &endpointU_0, _Out_ int8_t &endpointU_1, _Out_ int8_t &endpointV_0, _Out_ int8_t &endpointV_1)
{
//Encoding the U and V channel by BC4 codec separately.
FindEndPointsBC4S( theTexelsU, endpointU_0, endpointU_1);
FindEndPointsBC4S( theTexelsV, endpointV_0, endpointV_1);
}
//------------------------------------------------------------------------------
static void FindClosestUNORM(_Inout_ BC4_UNORM* pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const float theTexelsU[])
{
float rGradient[8];
int i;
for (i = 0; i < 8; ++i)
{
rGradient[i] = pBC->DecodeFromIndex(i);
}
for (i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
size_t uBestIndex = 0;
float fBestDelta = 100000;
for (size_t uIndex = 0; uIndex < 8; uIndex++)
{
float fCurrentDelta = fabsf(rGradient[uIndex]-theTexelsU[i]);
if (fCurrentDelta < fBestDelta)
{
uBestIndex = uIndex;
fBestDelta = fCurrentDelta;
}
}
pBC->SetIndex(i, uBestIndex);
}
}
static void FindClosestSNORM(_Inout_ BC4_SNORM* pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const float theTexelsU[])
{
float rGradient[8];
int i;
for (i = 0; i < 8; ++i)
{
rGradient[i] = pBC->DecodeFromIndex(i);
}
for (i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
size_t uBestIndex = 0;
float fBestDelta = 100000;
for (size_t uIndex = 0; uIndex < 8; uIndex++)
{
float fCurrentDelta = fabsf(rGradient[uIndex]-theTexelsU[i]);
if (fCurrentDelta < fBestDelta)
{
uBestIndex = uIndex;
fBestDelta = fCurrentDelta;
}
}
pBC->SetIndex(i, uBestIndex);
}
}
//=====================================================================================
// Entry points
//=====================================================================================
//-------------------------------------------------------------------------------------
// BC4 Compression
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
void D3DXDecodeBC4U( XMVECTOR *pColor, const uint8_t *pBC )
{
assert( pColor && pBC );
static_assert( sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes" );
auto pBC4 = reinterpret_cast<const BC4_UNORM*>(pBC);
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
#pragma prefast(suppress:22103, "writing blocks in two halves confuses tool")
pColor[i] = XMVectorSet( pBC4->R(i), 0, 0, 1.0f);
}
}
_Use_decl_annotations_
void D3DXDecodeBC4S(XMVECTOR *pColor, const uint8_t *pBC)
{
assert( pColor && pBC );
static_assert( sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes" );
auto pBC4 = reinterpret_cast<const BC4_SNORM*>(pBC);
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
#pragma prefast(suppress:22103, "writing blocks in two halves confuses tool")
pColor[i] = XMVectorSet( pBC4->R(i), 0, 0, 1.0f);
}
}
_Use_decl_annotations_
void D3DXEncodeBC4U( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
{
UNREFERENCED_PARAMETER( flags );
assert( pBC && pColor );
static_assert( sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes" );
memset(pBC, 0, sizeof(BC4_UNORM));
auto pBC4 = reinterpret_cast<BC4_UNORM*>(pBC);
float theTexelsU[NUM_PIXELS_PER_BLOCK];
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
theTexelsU[i] = XMVectorGetX( pColor[i] );
}
FindEndPointsBC4U(theTexelsU, pBC4->red_0, pBC4->red_1);
FindClosestUNORM(pBC4, theTexelsU);
}
_Use_decl_annotations_
void D3DXEncodeBC4S( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
{
UNREFERENCED_PARAMETER( flags );
assert( pBC && pColor );
static_assert( sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes" );
memset(pBC, 0, sizeof(BC4_UNORM));
auto pBC4 = reinterpret_cast<BC4_SNORM*>(pBC);
float theTexelsU[NUM_PIXELS_PER_BLOCK];
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
theTexelsU[i] = XMVectorGetX( pColor[i] );
}
FindEndPointsBC4S(theTexelsU, pBC4->red_0, pBC4->red_1);
FindClosestSNORM(pBC4, theTexelsU);
}
//-------------------------------------------------------------------------------------
// BC5 Compression
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
void D3DXDecodeBC5U(XMVECTOR *pColor, const uint8_t *pBC)
{
assert( pColor && pBC );
static_assert( sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes" );
auto pBCR = reinterpret_cast<const BC4_UNORM*>(pBC);
auto pBCG = reinterpret_cast<const BC4_UNORM*>(pBC+sizeof(BC4_UNORM));
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
#pragma prefast(suppress:22103, "writing blocks in two halves confuses tool")
pColor[i] = XMVectorSet(pBCR->R(i), pBCG->R(i), 0, 1.0f);
}
}
_Use_decl_annotations_
void D3DXDecodeBC5S(XMVECTOR *pColor, const uint8_t *pBC)
{
assert( pColor && pBC );
static_assert( sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes" );
auto pBCR = reinterpret_cast<const BC4_SNORM*>(pBC);
auto pBCG = reinterpret_cast<const BC4_SNORM*>(pBC+sizeof(BC4_SNORM));
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
#pragma prefast(suppress:22103, "writing blocks in two halves confuses tool")
pColor[i] = XMVectorSet(pBCR->R(i), pBCG->R(i), 0, 1.0f);
}
}
_Use_decl_annotations_
void D3DXEncodeBC5U( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
{
UNREFERENCED_PARAMETER( flags );
assert( pBC && pColor );
static_assert( sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes" );
memset(pBC, 0, sizeof(BC4_UNORM)*2);
auto pBCR = reinterpret_cast<BC4_UNORM*>(pBC);
auto pBCG = reinterpret_cast<BC4_UNORM*>(pBC+sizeof(BC4_UNORM));
float theTexelsU[NUM_PIXELS_PER_BLOCK];
float theTexelsV[NUM_PIXELS_PER_BLOCK];
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
XMFLOAT4A clr;
XMStoreFloat4A( &clr, pColor[i] );
theTexelsU[i] = clr.x;
theTexelsV[i] = clr.y;
}
FindEndPointsBC5U(
theTexelsU,
theTexelsV,
pBCR->red_0,
pBCR->red_1,
pBCG->red_0,
pBCG->red_1);
FindClosestUNORM(pBCR, theTexelsU);
FindClosestUNORM(pBCG, theTexelsV);
}
_Use_decl_annotations_
void D3DXEncodeBC5S( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
{
UNREFERENCED_PARAMETER( flags );
assert( pBC && pColor );
static_assert( sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes" );
memset(pBC, 0, sizeof(BC4_UNORM)*2);
auto pBCR = reinterpret_cast<BC4_SNORM*>(pBC);
auto pBCG = reinterpret_cast<BC4_SNORM*>(pBC+sizeof(BC4_SNORM));
float theTexelsU[NUM_PIXELS_PER_BLOCK];
float theTexelsV[NUM_PIXELS_PER_BLOCK];
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
XMFLOAT4A clr;
XMStoreFloat4A( &clr, pColor[i] );
theTexelsU[i] = clr.x;
theTexelsV[i] = clr.y;
}
FindEndPointsBC5S(
theTexelsU,
theTexelsV,
pBCR->red_0,
pBCR->red_1,
pBCG->red_0,
pBCG->red_1);
FindClosestSNORM(pBCR, theTexelsU);
FindClosestSNORM(pBCG, theTexelsV);
}
} // namespace

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,237 @@
//--------------------------------------------------------------------------------------
// dds.h
//
// This header defines constants and structures that are useful when parsing
// DDS files. DDS files were originally designed to use several structures
// and constants that are native to DirectDraw and are defined in ddraw.h,
// such as DDSURFACEDESC2 and DDSCAPS2. This file defines similar
// (compatible) constants and structures so that one can use DDS files
// without needing to include ddraw.h.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// http://go.microsoft.com/fwlink/?LinkId=248926
//--------------------------------------------------------------------------------------
#pragma once
#if defined(_XBOX_ONE) && defined(_TITLE)
#include <d3d11_x.h>
#else
#include <dxgiformat.h>
#endif
// VS 2010's stdint.h conflicts with intsafe.h
#pragma warning(push)
#pragma warning(disable : 4005)
#include <stdint.h>
#pragma warning(pop)
namespace DirectX
{
#pragma pack(push,1)
const uint32_t DDS_MAGIC = 0x20534444; // "DDS "
struct DDS_PIXELFORMAT
{
uint32_t dwSize;
uint32_t dwFlags;
uint32_t dwFourCC;
uint32_t dwRGBBitCount;
uint32_t dwRBitMask;
uint32_t dwGBitMask;
uint32_t dwBBitMask;
uint32_t dwABitMask;
};
#define DDS_FOURCC 0x00000004 // DDPF_FOURCC
#define DDS_RGB 0x00000040 // DDPF_RGB
#define DDS_RGBA 0x00000041 // DDPF_RGB | DDPF_ALPHAPIXELS
#define DDS_LUMINANCE 0x00020000 // DDPF_LUMINANCE
#define DDS_LUMINANCEA 0x00020001 // DDPF_LUMINANCE | DDPF_ALPHAPIXELS
#define DDS_ALPHA 0x00000002 // DDPF_ALPHA
#define DDS_PAL8 0x00000020 // DDPF_PALETTEINDEXED8
#ifndef MAKEFOURCC
#define MAKEFOURCC(ch0, ch1, ch2, ch3) \
((uint32_t)(uint8_t)(ch0) | ((uint32_t)(uint8_t)(ch1) << 8) | \
((uint32_t)(uint8_t)(ch2) << 16) | ((uint32_t)(uint8_t)(ch3) << 24 ))
#endif /* defined(MAKEFOURCC) */
extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DXT1 =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','1'), 0, 0, 0, 0, 0 };
extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DXT2 =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','2'), 0, 0, 0, 0, 0 };
extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DXT3 =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','3'), 0, 0, 0, 0, 0 };
extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DXT4 =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','4'), 0, 0, 0, 0, 0 };
extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DXT5 =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','5'), 0, 0, 0, 0, 0 };
extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_BC4_UNORM =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','4','U'), 0, 0, 0, 0, 0 };
extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_BC4_SNORM =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','4','S'), 0, 0, 0, 0, 0 };
extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_BC5_UNORM =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','5','U'), 0, 0, 0, 0, 0 };
extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_BC5_SNORM =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','5','S'), 0, 0, 0, 0, 0 };
extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_R8G8_B8G8 =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('R','G','B','G'), 0, 0, 0, 0, 0 };
extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_G8R8_G8B8 =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('G','R','G','B'), 0, 0, 0, 0, 0 };
extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_YUY2 =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('Y','U','Y','2'), 0, 0, 0, 0, 0 };
extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A8R8G8B8 =
{ sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 };
extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_X8R8G8B8 =
{ sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 };
extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A8B8G8R8 =
{ sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 };
extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_X8B8G8R8 =
{ sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000 };
extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_G16R16 =
{ sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 32, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000 };
extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_R5G6B5 =
{ sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 16, 0x0000f800, 0x000007e0, 0x0000001f, 0x00000000 };
extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A1R5G5B5 =
{ sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x00007c00, 0x000003e0, 0x0000001f, 0x00008000 };
extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A4R4G4B4 =
{ sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x00000f00, 0x000000f0, 0x0000000f, 0x0000f000 };
extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_R8G8B8 =
{ sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 };
extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_L8 =
{ sizeof(DDS_PIXELFORMAT), DDS_LUMINANCE, 0, 8, 0xff, 0x00, 0x00, 0x00 };
extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_L16 =
{ sizeof(DDS_PIXELFORMAT), DDS_LUMINANCE, 0, 16, 0xffff, 0x0000, 0x0000, 0x0000 };
extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A8L8 =
{ sizeof(DDS_PIXELFORMAT), DDS_LUMINANCEA, 0, 16, 0x00ff, 0x0000, 0x0000, 0xff00 };
extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A8 =
{ sizeof(DDS_PIXELFORMAT), DDS_ALPHA, 0, 8, 0x00, 0x00, 0x00, 0xff };
// D3DFMT_A2R10G10B10/D3DFMT_A2B10G10R10 should be written using DX10 extension to avoid D3DX 10:10:10:2 reversal issue
// This indicates the DDS_HEADER_DXT10 extension is present (the format is in dxgiFormat)
extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DX10 =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','1','0'), 0, 0, 0, 0, 0 };
#define DDS_HEADER_FLAGS_TEXTURE 0x00001007 // DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT
#define DDS_HEADER_FLAGS_MIPMAP 0x00020000 // DDSD_MIPMAPCOUNT
#define DDS_HEADER_FLAGS_VOLUME 0x00800000 // DDSD_DEPTH
#define DDS_HEADER_FLAGS_PITCH 0x00000008 // DDSD_PITCH
#define DDS_HEADER_FLAGS_LINEARSIZE 0x00080000 // DDSD_LINEARSIZE
#define DDS_HEIGHT 0x00000002 // DDSD_HEIGHT
#define DDS_WIDTH 0x00000004 // DDSD_WIDTH
#define DDS_SURFACE_FLAGS_TEXTURE 0x00001000 // DDSCAPS_TEXTURE
#define DDS_SURFACE_FLAGS_MIPMAP 0x00400008 // DDSCAPS_COMPLEX | DDSCAPS_MIPMAP
#define DDS_SURFACE_FLAGS_CUBEMAP 0x00000008 // DDSCAPS_COMPLEX
#define DDS_CUBEMAP_POSITIVEX 0x00000600 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX
#define DDS_CUBEMAP_NEGATIVEX 0x00000a00 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEX
#define DDS_CUBEMAP_POSITIVEY 0x00001200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEY
#define DDS_CUBEMAP_NEGATIVEY 0x00002200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEY
#define DDS_CUBEMAP_POSITIVEZ 0x00004200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEZ
#define DDS_CUBEMAP_NEGATIVEZ 0x00008200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEZ
#define DDS_CUBEMAP_ALLFACES ( DDS_CUBEMAP_POSITIVEX | DDS_CUBEMAP_NEGATIVEX |\
DDS_CUBEMAP_POSITIVEY | DDS_CUBEMAP_NEGATIVEY |\
DDS_CUBEMAP_POSITIVEZ | DDS_CUBEMAP_NEGATIVEZ )
#define DDS_CUBEMAP 0x00000200 // DDSCAPS2_CUBEMAP
#define DDS_FLAGS_VOLUME 0x00200000 // DDSCAPS2_VOLUME
// Subset here matches D3D10_RESOURCE_DIMENSION and D3D11_RESOURCE_DIMENSION
enum DDS_RESOURCE_DIMENSION
{
DDS_DIMENSION_TEXTURE1D = 2,
DDS_DIMENSION_TEXTURE2D = 3,
DDS_DIMENSION_TEXTURE3D = 4,
};
// Subset here matches D3D10_RESOURCE_MISC_FLAG and D3D11_RESOURCE_MISC_FLAG
enum DDS_RESOURCE_MISC_FLAG
{
DDS_RESOURCE_MISC_TEXTURECUBE = 0x4L,
};
enum DDS_MISC_FLAGS2
{
DDS_MISC_FLAGS2_ALPHA_MODE_MASK = 0x7L,
};
enum DDS_ALPHA_MODE
{
DDS_ALPHA_MODE_UNKNOWN = 0,
DDS_ALPHA_MODE_STRAIGHT = 1,
DDS_ALPHA_MODE_PREMULTIPLIED = 2,
DDS_ALPHA_MODE_OPAQUE = 3,
DDS_ALPHA_MODE_CUSTOM = 4,
};
struct DDS_HEADER
{
uint32_t dwSize;
uint32_t dwFlags;
uint32_t dwHeight;
uint32_t dwWidth;
uint32_t dwPitchOrLinearSize;
uint32_t dwDepth; // only if DDS_HEADER_FLAGS_VOLUME is set in dwFlags
uint32_t dwMipMapCount;
uint32_t dwReserved1[11];
DDS_PIXELFORMAT ddspf;
uint32_t dwCaps;
uint32_t dwCaps2;
uint32_t dwCaps3;
uint32_t dwCaps4;
uint32_t dwReserved2;
};
struct DDS_HEADER_DXT10
{
DXGI_FORMAT dxgiFormat;
uint32_t resourceDimension;
uint32_t miscFlag; // see DDS_RESOURCE_MISC_FLAG
uint32_t arraySize;
uint32_t miscFlags2; // see DDS_MISC_FLAGS2
};
#pragma pack(pop)
static_assert( sizeof(DDS_HEADER) == 124, "DDS Header size mismatch" );
static_assert( sizeof(DDS_HEADER_DXT10) == 20, "DDS DX10 Extended Header size mismatch");
}; // namespace

View file

@ -0,0 +1,654 @@
//-------------------------------------------------------------------------------------
// DirectXTex.h
//
// DirectX Texture Library
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// http://go.microsoft.com/fwlink/?LinkId=248926
//-------------------------------------------------------------------------------------
#pragma once
#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) && (_WIN32_WINNT <= _WIN32_WINNT_WIN8)
#error WIC is not supported on Windows Phone 8.0
#endif
// VS 2010's stdint.h conflicts with intsafe.h
#pragma warning(push)
#pragma warning(disable : 4005)
#include <stdint.h>
#pragma warning(pop)
#include <algorithm>
#include <functional>
#if defined(_XBOX_ONE) && defined(_TITLE)
#include <d3d11_x.h>
#define DCOMMON_H_INCLUDED
#else
#include <d3d11_1.h>
#endif
#include <ocidl.h>
// VS 2010 doesn't support explicit calling convention for std::function
#ifndef DIRECTX_STD_CALLCONV
#if defined(_MSC_VER) && (_MSC_VER < 1700)
#define DIRECTX_STD_CALLCONV
#else
#define DIRECTX_STD_CALLCONV __cdecl
#endif
#endif
// VS 2010/2012 do not support =default =delete
#ifndef DIRECTX_CTOR_DEFAULT
#if defined(_MSC_VER) && (_MSC_VER < 1800)
#define DIRECTX_CTOR_DEFAULT {}
#define DIRECTX_CTOR_DELETE ;
#else
#define DIRECTX_CTOR_DEFAULT =default;
#define DIRECTX_CTOR_DELETE =delete;
#endif
#endif
#define DIRECTX_TEX_VERSION 133
struct IWICImagingFactory;
namespace DirectX
{
//---------------------------------------------------------------------------------
// DXGI Format Utilities
bool __cdecl IsValid( _In_ DXGI_FORMAT fmt );
bool __cdecl IsCompressed( _In_ DXGI_FORMAT fmt );
bool __cdecl IsPacked( _In_ DXGI_FORMAT fmt );
bool __cdecl IsVideo( _In_ DXGI_FORMAT fmt );
bool __cdecl IsPlanar( _In_ DXGI_FORMAT fmt );
bool __cdecl IsPalettized( _In_ DXGI_FORMAT fmt );
bool __cdecl IsDepthStencil(_In_ DXGI_FORMAT fmt );
bool __cdecl IsSRGB( _In_ DXGI_FORMAT fmt );
bool __cdecl IsTypeless( _In_ DXGI_FORMAT fmt, _In_ bool partialTypeless = true );
bool __cdecl HasAlpha( _In_ DXGI_FORMAT fmt );
size_t __cdecl BitsPerPixel( _In_ DXGI_FORMAT fmt );
size_t __cdecl BitsPerColor( _In_ DXGI_FORMAT fmt );
enum CP_FLAGS
{
CP_FLAGS_NONE = 0x0, // Normal operation
CP_FLAGS_LEGACY_DWORD = 0x1, // Assume pitch is DWORD aligned instead of BYTE aligned
CP_FLAGS_PARAGRAPH = 0x2, // Assume pitch is 16-byte aligned instead of BYTE aligned
CP_FLAGS_YMM = 0x4, // Assume pitch is 32-byte aligned instead of BYTE aligned
CP_FLAGS_ZMM = 0x8, // Assume pitch is 64-byte aligned instead of BYTE aligned
CP_FLAGS_PAGE4K = 0x200, // Assume pitch is 4096-byte aligned instead of BYTE aligned
CP_FLAGS_24BPP = 0x10000, // Override with a legacy 24 bits-per-pixel format size
CP_FLAGS_16BPP = 0x20000, // Override with a legacy 16 bits-per-pixel format size
CP_FLAGS_8BPP = 0x40000, // Override with a legacy 8 bits-per-pixel format size
};
void __cdecl ComputePitch( _In_ DXGI_FORMAT fmt, _In_ size_t width, _In_ size_t height,
_Out_ size_t& rowPitch, _Out_ size_t& slicePitch, _In_ DWORD flags = CP_FLAGS_NONE );
size_t __cdecl ComputeScanlines( _In_ DXGI_FORMAT fmt, _In_ size_t height );
DXGI_FORMAT __cdecl MakeSRGB( _In_ DXGI_FORMAT fmt );
DXGI_FORMAT __cdecl MakeTypeless( _In_ DXGI_FORMAT fmt );
DXGI_FORMAT __cdecl MakeTypelessUNORM( _In_ DXGI_FORMAT fmt );
DXGI_FORMAT __cdecl MakeTypelessFLOAT( _In_ DXGI_FORMAT fmt );
//---------------------------------------------------------------------------------
// Texture metadata
enum TEX_DIMENSION
// Subset here matches D3D10_RESOURCE_DIMENSION and D3D11_RESOURCE_DIMENSION
{
TEX_DIMENSION_TEXTURE1D = 2,
TEX_DIMENSION_TEXTURE2D = 3,
TEX_DIMENSION_TEXTURE3D = 4,
};
enum TEX_MISC_FLAG
// Subset here matches D3D10_RESOURCE_MISC_FLAG and D3D11_RESOURCE_MISC_FLAG
{
TEX_MISC_TEXTURECUBE = 0x4L,
};
enum TEX_MISC_FLAG2
{
TEX_MISC2_ALPHA_MODE_MASK = 0x7L,
};
enum TEX_ALPHA_MODE
// Matches DDS_ALPHA_MODE, encoded in MISC_FLAGS2
{
TEX_ALPHA_MODE_UNKNOWN = 0,
TEX_ALPHA_MODE_STRAIGHT = 1,
TEX_ALPHA_MODE_PREMULTIPLIED = 2,
TEX_ALPHA_MODE_OPAQUE = 3,
TEX_ALPHA_MODE_CUSTOM = 4,
};
struct TexMetadata
{
size_t width;
size_t height; // Should be 1 for 1D textures
size_t depth; // Should be 1 for 1D or 2D textures
size_t arraySize; // For cubemap, this is a multiple of 6
size_t mipLevels;
uint32_t miscFlags;
uint32_t miscFlags2;
DXGI_FORMAT format;
TEX_DIMENSION dimension;
size_t __cdecl ComputeIndex( _In_ size_t mip, _In_ size_t item, _In_ size_t slice ) const;
// Returns size_t(-1) to indicate an out-of-range error
bool __cdecl IsCubemap() const { return (miscFlags & TEX_MISC_TEXTURECUBE) != 0; }
// Helper for miscFlags
bool __cdecl IsPMAlpha() const { return ((miscFlags2 & TEX_MISC2_ALPHA_MODE_MASK) == TEX_ALPHA_MODE_PREMULTIPLIED) != 0; }
void __cdecl SetAlphaMode( TEX_ALPHA_MODE mode ) { miscFlags2 = (miscFlags2 & ~TEX_MISC2_ALPHA_MODE_MASK) | static_cast<uint32_t>(mode); }
// Helpers for miscFlags2
bool __cdecl IsVolumemap() const { return (dimension == TEX_DIMENSION_TEXTURE3D); }
// Helper for dimension
};
enum DDS_FLAGS
{
DDS_FLAGS_NONE = 0x0,
DDS_FLAGS_LEGACY_DWORD = 0x1,
// Assume pitch is DWORD aligned instead of BYTE aligned (used by some legacy DDS files)
DDS_FLAGS_NO_LEGACY_EXPANSION = 0x2,
// Do not implicitly convert legacy formats that result in larger pixel sizes (24 bpp, 3:3:2, A8L8, A4L4, P8, A8P8)
DDS_FLAGS_NO_R10B10G10A2_FIXUP = 0x4,
// Do not use work-around for long-standing D3DX DDS file format issue which reversed the 10:10:10:2 color order masks
DDS_FLAGS_FORCE_RGB = 0x8,
// Convert DXGI 1.1 BGR formats to DXGI_FORMAT_R8G8B8A8_UNORM to avoid use of optional WDDM 1.1 formats
DDS_FLAGS_NO_16BPP = 0x10,
// Conversions avoid use of 565, 5551, and 4444 formats and instead expand to 8888 to avoid use of optional WDDM 1.2 formats
DDS_FLAGS_EXPAND_LUMINANCE = 0x20,
// When loading legacy luminance formats expand replicating the color channels rather than leaving them packed (L8, L16, A8L8)
DDS_FLAGS_FORCE_DX10_EXT = 0x10000,
// Always use the 'DX10' header extension for DDS writer (i.e. don't try to write DX9 compatible DDS files)
DDS_FLAGS_FORCE_DX10_EXT_MISC2 = 0x20000,
// DDS_FLAGS_FORCE_DX10_EXT including miscFlags2 information (result may not be compatible with D3DX10 or D3DX11)
};
enum WIC_FLAGS
{
WIC_FLAGS_NONE = 0x0,
WIC_FLAGS_FORCE_RGB = 0x1,
// Loads DXGI 1.1 BGR formats as DXGI_FORMAT_R8G8B8A8_UNORM to avoid use of optional WDDM 1.1 formats
WIC_FLAGS_NO_X2_BIAS = 0x2,
// Loads DXGI 1.1 X2 10:10:10:2 format as DXGI_FORMAT_R10G10B10A2_UNORM
WIC_FLAGS_NO_16BPP = 0x4,
// Loads 565, 5551, and 4444 formats as 8888 to avoid use of optional WDDM 1.2 formats
WIC_FLAGS_ALLOW_MONO = 0x8,
// Loads 1-bit monochrome (black & white) as R1_UNORM rather than 8-bit grayscale
WIC_FLAGS_ALL_FRAMES = 0x10,
// Loads all images in a multi-frame file, converting/resizing to match the first frame as needed, defaults to 0th frame otherwise
WIC_FLAGS_IGNORE_SRGB = 0x20,
// Ignores sRGB metadata if present in the file
WIC_FLAGS_DITHER = 0x10000,
// Use ordered 4x4 dithering for any required conversions
WIC_FLAGS_DITHER_DIFFUSION = 0x20000,
// Use error-diffusion dithering for any required conversions
WIC_FLAGS_FILTER_POINT = 0x100000,
WIC_FLAGS_FILTER_LINEAR = 0x200000,
WIC_FLAGS_FILTER_CUBIC = 0x300000,
WIC_FLAGS_FILTER_FANT = 0x400000, // Combination of Linear and Box filter
// Filtering mode to use for any required image resizing (only needed when loading arrays of differently sized images; defaults to Fant)
};
HRESULT __cdecl GetMetadataFromDDSMemory( _In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size, _In_ DWORD flags,
_Out_ TexMetadata& metadata );
HRESULT __cdecl GetMetadataFromDDSFile( _In_z_ LPCWSTR szFile, _In_ DWORD flags,
_Out_ TexMetadata& metadata );
HRESULT __cdecl GetMetadataFromTGAMemory( _In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size,
_Out_ TexMetadata& metadata );
HRESULT __cdecl GetMetadataFromTGAFile( _In_z_ LPCWSTR szFile,
_Out_ TexMetadata& metadata );
HRESULT __cdecl GetMetadataFromWICMemory( _In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size, _In_ DWORD flags,
_Out_ TexMetadata& metadata );
HRESULT __cdecl GetMetadataFromWICFile( _In_z_ LPCWSTR szFile, _In_ DWORD flags,
_Out_ TexMetadata& metadata );
//---------------------------------------------------------------------------------
// Bitmap image container
struct Image
{
size_t width;
size_t height;
DXGI_FORMAT format;
size_t rowPitch;
size_t slicePitch;
uint8_t* pixels;
};
class ScratchImage
{
public:
ScratchImage()
: _nimages(0), _size(0), _image(nullptr), _memory(nullptr) {}
ScratchImage(ScratchImage&& moveFrom)
: _nimages(0), _size(0), _image(nullptr), _memory(nullptr) { *this = std::move(moveFrom); }
~ScratchImage() { Release(); }
ScratchImage& __cdecl operator= (ScratchImage&& moveFrom);
HRESULT __cdecl Initialize( _In_ const TexMetadata& mdata, _In_ DWORD flags = CP_FLAGS_NONE );
HRESULT __cdecl Initialize1D( _In_ DXGI_FORMAT fmt, _In_ size_t length, _In_ size_t arraySize, _In_ size_t mipLevels, _In_ DWORD flags = CP_FLAGS_NONE );
HRESULT __cdecl Initialize2D( _In_ DXGI_FORMAT fmt, _In_ size_t width, _In_ size_t height, _In_ size_t arraySize, _In_ size_t mipLevels, _In_ DWORD flags = CP_FLAGS_NONE );
HRESULT __cdecl Initialize3D( _In_ DXGI_FORMAT fmt, _In_ size_t width, _In_ size_t height, _In_ size_t depth, _In_ size_t mipLevels, _In_ DWORD flags = CP_FLAGS_NONE );
HRESULT __cdecl InitializeCube( _In_ DXGI_FORMAT fmt, _In_ size_t width, _In_ size_t height, _In_ size_t nCubes, _In_ size_t mipLevels, _In_ DWORD flags = CP_FLAGS_NONE );
HRESULT __cdecl InitializeFromImage( _In_ const Image& srcImage, _In_ bool allow1D = false, _In_ DWORD flags = CP_FLAGS_NONE );
HRESULT __cdecl InitializeArrayFromImages( _In_reads_(nImages) const Image* images, _In_ size_t nImages, _In_ bool allow1D = false, _In_ DWORD flags = CP_FLAGS_NONE );
HRESULT __cdecl InitializeCubeFromImages( _In_reads_(nImages) const Image* images, _In_ size_t nImages, _In_ DWORD flags = CP_FLAGS_NONE );
HRESULT __cdecl Initialize3DFromImages( _In_reads_(depth) const Image* images, _In_ size_t depth, _In_ DWORD flags = CP_FLAGS_NONE );
void __cdecl Release();
bool __cdecl OverrideFormat( _In_ DXGI_FORMAT f );
const TexMetadata& __cdecl GetMetadata() const { return _metadata; }
const Image* __cdecl GetImage(_In_ size_t mip, _In_ size_t item, _In_ size_t slice) const;
const Image* __cdecl GetImages() const { return _image; }
size_t __cdecl GetImageCount() const { return _nimages; }
uint8_t* __cdecl GetPixels() const { return _memory; }
size_t __cdecl GetPixelsSize() const { return _size; }
bool __cdecl IsAlphaAllOpaque() const;
private:
size_t _nimages;
size_t _size;
TexMetadata _metadata;
Image* _image;
uint8_t* _memory;
// Hide copy constructor and assignment operator
ScratchImage( const ScratchImage& );
ScratchImage& operator=( const ScratchImage& );
};
//---------------------------------------------------------------------------------
// Memory blob (allocated buffer pointer is always 16-byte aligned)
class Blob
{
public:
Blob() : _buffer(nullptr), _size(0) {}
Blob(Blob&& moveFrom) : _buffer(nullptr), _size(0) { *this = std::move(moveFrom); }
~Blob() { Release(); }
Blob& __cdecl operator= (Blob&& moveFrom);
HRESULT __cdecl Initialize( _In_ size_t size );
void __cdecl Release();
void *__cdecl GetBufferPointer() const { return _buffer; }
size_t __cdecl GetBufferSize() const { return _size; }
private:
void* _buffer;
size_t _size;
// Hide copy constructor and assignment operator
Blob( const Blob& );
Blob& operator=( const Blob& );
};
//---------------------------------------------------------------------------------
// Image I/O
// DDS operations
HRESULT __cdecl LoadFromDDSMemory( _In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size, _In_ DWORD flags,
_Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image );
HRESULT __cdecl LoadFromDDSFile( _In_z_ LPCWSTR szFile, _In_ DWORD flags,
_Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image );
HRESULT __cdecl SaveToDDSMemory( _In_ const Image& image, _In_ DWORD flags,
_Out_ Blob& blob );
HRESULT __cdecl SaveToDDSMemory( _In_reads_(nimages) const Image* images, _In_ size_t nimages, _In_ const TexMetadata& metadata, _In_ DWORD flags,
_Out_ Blob& blob );
HRESULT __cdecl SaveToDDSFile( _In_ const Image& image, _In_ DWORD flags, _In_z_ LPCWSTR szFile );
HRESULT __cdecl SaveToDDSFile( _In_reads_(nimages) const Image* images, _In_ size_t nimages, _In_ const TexMetadata& metadata, _In_ DWORD flags, _In_z_ LPCWSTR szFile );
// TGA operations
HRESULT __cdecl LoadFromTGAMemory( _In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size,
_Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image );
HRESULT __cdecl LoadFromTGAFile( _In_z_ LPCWSTR szFile,
_Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image );
HRESULT __cdecl SaveToTGAMemory( _In_ const Image& image, _Out_ Blob& blob );
HRESULT __cdecl SaveToTGAFile( _In_ const Image& image, _In_z_ LPCWSTR szFile );
// WIC operations
HRESULT __cdecl LoadFromWICMemory( _In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size, _In_ DWORD flags,
_Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image );
HRESULT __cdecl LoadFromWICFile( _In_z_ LPCWSTR szFile, _In_ DWORD flags,
_Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image );
HRESULT __cdecl SaveToWICMemory( _In_ const Image& image, _In_ DWORD flags, _In_ REFGUID guidContainerFormat,
_Out_ Blob& blob, _In_opt_ const GUID* targetFormat = nullptr,
_In_opt_ std::function<void DIRECTX_STD_CALLCONV(IPropertyBag2*)> setCustomProps = nullptr );
HRESULT __cdecl SaveToWICMemory( _In_count_(nimages) const Image* images, _In_ size_t nimages, _In_ DWORD flags, _In_ REFGUID guidContainerFormat,
_Out_ Blob& blob, _In_opt_ const GUID* targetFormat = nullptr,
_In_opt_ std::function<void DIRECTX_STD_CALLCONV(IPropertyBag2*)> setCustomProps = nullptr );
HRESULT __cdecl SaveToWICFile( _In_ const Image& image, _In_ DWORD flags, _In_ REFGUID guidContainerFormat,
_In_z_ LPCWSTR szFile, _In_opt_ const GUID* targetFormat = nullptr,
_In_opt_ std::function<void DIRECTX_STD_CALLCONV(IPropertyBag2*)> setCustomProps = nullptr );
HRESULT __cdecl SaveToWICFile( _In_count_(nimages) const Image* images, _In_ size_t nimages, _In_ DWORD flags, _In_ REFGUID guidContainerFormat,
_In_z_ LPCWSTR szFile, _In_opt_ const GUID* targetFormat = nullptr,
_In_opt_ std::function<void DIRECTX_STD_CALLCONV(IPropertyBag2*)> setCustomProps = nullptr );
//---------------------------------------------------------------------------------
// Texture conversion, resizing, mipmap generation, and block compression
enum TEX_FR_FLAGS
{
TEX_FR_ROTATE0 = 0x0,
TEX_FR_ROTATE90 = 0x1,
TEX_FR_ROTATE180 = 0x2,
TEX_FR_ROTATE270 = 0x3,
TEX_FR_FLIP_HORIZONTAL = 0x08,
TEX_FR_FLIP_VERTICAL = 0x10,
};
HRESULT __cdecl FlipRotate( _In_ const Image& srcImage, _In_ DWORD flags, _Out_ ScratchImage& image );
HRESULT __cdecl FlipRotate( _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
_In_ DWORD flags, _Out_ ScratchImage& result );
// Flip and/or rotate image
enum TEX_FILTER_FLAGS
{
TEX_FILTER_DEFAULT = 0,
TEX_FILTER_WRAP_U = 0x1,
TEX_FILTER_WRAP_V = 0x2,
TEX_FILTER_WRAP_W = 0x4,
TEX_FILTER_WRAP = ( TEX_FILTER_WRAP_U | TEX_FILTER_WRAP_V | TEX_FILTER_WRAP_W ),
TEX_FILTER_MIRROR_U = 0x10,
TEX_FILTER_MIRROR_V = 0x20,
TEX_FILTER_MIRROR_W = 0x40,
TEX_FILTER_MIRROR = ( TEX_FILTER_MIRROR_U | TEX_FILTER_MIRROR_V | TEX_FILTER_MIRROR_W ),
// Wrap vs. Mirror vs. Clamp filtering options
TEX_FILTER_SEPARATE_ALPHA = 0x100,
// Resize color and alpha channel independently
TEX_FILTER_RGB_COPY_RED = 0x1000,
TEX_FILTER_RGB_COPY_GREEN = 0x2000,
TEX_FILTER_RGB_COPY_BLUE = 0x4000,
// When converting RGB to R, defaults to using grayscale. These flags indicate copying a specific channel instead
// When converting RGB to RG, defaults to copying RED | GREEN. These flags control which channels are selected instead.
TEX_FILTER_DITHER = 0x10000,
// Use ordered 4x4 dithering for any required conversions
TEX_FILTER_DITHER_DIFFUSION = 0x20000,
// Use error-diffusion dithering for any required conversions
TEX_FILTER_POINT = 0x100000,
TEX_FILTER_LINEAR = 0x200000,
TEX_FILTER_CUBIC = 0x300000,
TEX_FILTER_BOX = 0x400000,
TEX_FILTER_FANT = 0x400000, // Equiv to Box filtering for mipmap generation
TEX_FILTER_TRIANGLE = 0x500000,
// Filtering mode to use for any required image resizing
TEX_FILTER_SRGB_IN = 0x1000000,
TEX_FILTER_SRGB_OUT = 0x2000000,
TEX_FILTER_SRGB = ( TEX_FILTER_SRGB_IN | TEX_FILTER_SRGB_OUT ),
// sRGB <-> RGB for use in conversion operations
// if the input format type is IsSRGB(), then SRGB_IN is on by default
// if the output format type is IsSRGB(), then SRGB_OUT is on by default
TEX_FILTER_FORCE_NON_WIC = 0x10000000,
// Forces use of the non-WIC path when both are an option
TEX_FILTER_FORCE_WIC = 0x20000000,
// Forces use of the WIC path even when logic would have picked a non-WIC path when both are an option
};
HRESULT __cdecl Resize( _In_ const Image& srcImage, _In_ size_t width, _In_ size_t height, _In_ DWORD filter,
_Out_ ScratchImage& image );
HRESULT __cdecl Resize( _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
_In_ size_t width, _In_ size_t height, _In_ DWORD filter, _Out_ ScratchImage& result );
// Resize the image to width x height. Defaults to Fant filtering.
// Note for a complex resize, the result will always have mipLevels == 1
HRESULT __cdecl Convert( _In_ const Image& srcImage, _In_ DXGI_FORMAT format, _In_ DWORD filter, _In_ float threshold,
_Out_ ScratchImage& image );
HRESULT __cdecl Convert( _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
_In_ DXGI_FORMAT format, _In_ DWORD filter, _In_ float threshold, _Out_ ScratchImage& result );
// Convert the image to a new format
HRESULT __cdecl ConvertToSinglePlane( _In_ const Image& srcImage, _Out_ ScratchImage& image );
HRESULT __cdecl ConvertToSinglePlane( _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
_Out_ ScratchImage& image );
// Converts the image from a planar format to an equivalent non-planar format
HRESULT __cdecl GenerateMipMaps( _In_ const Image& baseImage, _In_ DWORD filter, _In_ size_t levels,
_Inout_ ScratchImage& mipChain, _In_ bool allow1D = false );
HRESULT __cdecl GenerateMipMaps( _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
_In_ DWORD filter, _In_ size_t levels, _Inout_ ScratchImage& mipChain );
// levels of '0' indicates a full mipchain, otherwise is generates that number of total levels (including the source base image)
// Defaults to Fant filtering which is equivalent to a box filter
HRESULT __cdecl GenerateMipMaps3D( _In_reads_(depth) const Image* baseImages, _In_ size_t depth, _In_ DWORD filter, _In_ size_t levels,
_Out_ ScratchImage& mipChain );
HRESULT __cdecl GenerateMipMaps3D( _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
_In_ DWORD filter, _In_ size_t levels, _Out_ ScratchImage& mipChain );
// levels of '0' indicates a full mipchain, otherwise is generates that number of total levels (including the source base image)
// Defaults to Fant filtering which is equivalent to a box filter
enum TEX_PMALPHA_FLAGS
{
TEX_PMALPHA_DEFAULT = 0,
TEX_PMALPHA_IGNORE_SRGB = 0x1,
// ignores sRGB colorspace conversions
TEX_PMALPHA_SRGB_IN = 0x1000000,
TEX_PMALPHA_SRGB_OUT = 0x2000000,
TEX_PMALPHA_SRGB = ( TEX_PMALPHA_SRGB_IN | TEX_PMALPHA_SRGB_OUT ),
// if the input format type is IsSRGB(), then SRGB_IN is on by default
// if the output format type is IsSRGB(), then SRGB_OUT is on by default
};
HRESULT __cdecl PremultiplyAlpha( _In_ const Image& srcImage, _In_ DWORD flags, _Out_ ScratchImage& image );
HRESULT __cdecl PremultiplyAlpha( _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata, _In_ DWORD flags, _Out_ ScratchImage& result );
// Converts to a premultiplied alpha version of the texture
enum TEX_COMPRESS_FLAGS
{
TEX_COMPRESS_DEFAULT = 0,
TEX_COMPRESS_RGB_DITHER = 0x10000,
// Enables dithering RGB colors for BC1-3 compression
TEX_COMPRESS_A_DITHER = 0x20000,
// Enables dithering alpha for BC1-3 compression
TEX_COMPRESS_DITHER = 0x30000,
// Enables both RGB and alpha dithering for BC1-3 compression
TEX_COMPRESS_UNIFORM = 0x40000,
// Uniform color weighting for BC1-3 compression; by default uses perceptual weighting
TEX_COMPRESS_BC7_USE_3SUBSETS = 0x80000,
// Enables exhaustive search for BC7 compress for mode 0 and 2; by default skips trying these modes
TEX_COMPRESS_SRGB_IN = 0x1000000,
TEX_COMPRESS_SRGB_OUT = 0x2000000,
TEX_COMPRESS_SRGB = ( TEX_COMPRESS_SRGB_IN | TEX_COMPRESS_SRGB_OUT ),
// if the input format type is IsSRGB(), then SRGB_IN is on by default
// if the output format type is IsSRGB(), then SRGB_OUT is on by default
TEX_COMPRESS_PARALLEL = 0x10000000,
// Compress is free to use multithreading to improve performance (by default it does not use multithreading)
};
HRESULT __cdecl Compress( _In_ const Image& srcImage, _In_ DXGI_FORMAT format, _In_ DWORD compress, _In_ float alphaRef,
_Out_ ScratchImage& cImage );
HRESULT __cdecl Compress( _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
_In_ DXGI_FORMAT format, _In_ DWORD compress, _In_ float alphaRef, _Out_ ScratchImage& cImages );
// Note that alphaRef is only used by BC1. 0.5f is a typical value to use
HRESULT __cdecl Compress( _In_ ID3D11Device* pDevice, _In_ const Image& srcImage, _In_ DXGI_FORMAT format, _In_ DWORD compress,
_In_ float alphaWeight, _Out_ ScratchImage& image );
HRESULT __cdecl Compress( _In_ ID3D11Device* pDevice, _In_ const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
_In_ DXGI_FORMAT format, _In_ DWORD compress, _In_ float alphaWeight, _Out_ ScratchImage& cImages );
// DirectCompute-based compression (alphaWeight is only used by BC7. 1.0 is the typical value to use)
HRESULT __cdecl Decompress( _In_ const Image& cImage, _In_ DXGI_FORMAT format, _Out_ ScratchImage& image );
HRESULT __cdecl Decompress( _In_reads_(nimages) const Image* cImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
_In_ DXGI_FORMAT format, _Out_ ScratchImage& images );
//---------------------------------------------------------------------------------
// Normal map operations
enum CNMAP_FLAGS
{
CNMAP_DEFAULT = 0,
CNMAP_CHANNEL_RED = 0x1,
CNMAP_CHANNEL_GREEN = 0x2,
CNMAP_CHANNEL_BLUE = 0x3,
CNMAP_CHANNEL_ALPHA = 0x4,
CNMAP_CHANNEL_LUMINANCE = 0x5,
// Channel selection when evaluting color value for height
// Luminance is a combination of red, green, and blue
CNMAP_MIRROR_U = 0x1000,
CNMAP_MIRROR_V = 0x2000,
CNMAP_MIRROR = 0x3000,
// Use mirror semantics for scanline references (defaults to wrap)
CNMAP_INVERT_SIGN = 0x4000,
// Inverts normal sign
CNMAP_COMPUTE_OCCLUSION = 0x8000,
// Computes a crude occlusion term stored in the alpha channel
};
HRESULT __cdecl ComputeNormalMap( _In_ const Image& srcImage, _In_ DWORD flags, _In_ float amplitude,
_In_ DXGI_FORMAT format, _Out_ ScratchImage& normalMap );
HRESULT __cdecl ComputeNormalMap( _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
_In_ DWORD flags, _In_ float amplitude, _In_ DXGI_FORMAT format, _Out_ ScratchImage& normalMaps );
//---------------------------------------------------------------------------------
// Misc image operations
struct Rect
{
size_t x;
size_t y;
size_t w;
size_t h;
Rect() DIRECTX_CTOR_DEFAULT
Rect( size_t _x, size_t _y, size_t _w, size_t _h ) : x(_x), y(_y), w(_w), h(_h) {}
};
HRESULT __cdecl CopyRectangle( _In_ const Image& srcImage, _In_ const Rect& srcRect, _In_ const Image& dstImage,
_In_ DWORD filter, _In_ size_t xOffset, _In_ size_t yOffset );
enum CMSE_FLAGS
{
CMSE_DEFAULT = 0,
CMSE_IMAGE1_SRGB = 0x1,
CMSE_IMAGE2_SRGB = 0x2,
// Indicates that image needs gamma correction before comparision
CMSE_IGNORE_RED = 0x10,
CMSE_IGNORE_GREEN = 0x20,
CMSE_IGNORE_BLUE = 0x40,
CMSE_IGNORE_ALPHA = 0x80,
// Ignore the channel when computing MSE
CMSE_IMAGE1_X2_BIAS = 0x100,
CMSE_IMAGE2_X2_BIAS = 0x200,
// Indicates that image should be scaled and biased before comparison (i.e. UNORM -> SNORM)
};
HRESULT __cdecl ComputeMSE( _In_ const Image& image1, _In_ const Image& image2, _Out_ float& mse, _Out_writes_opt_(4) float* mseV, _In_ DWORD flags = 0 );
//---------------------------------------------------------------------------------
// WIC utility code
enum WICCodecs
{
WIC_CODEC_BMP = 1, // Windows Bitmap (.bmp)
WIC_CODEC_JPEG, // Joint Photographic Experts Group (.jpg, .jpeg)
WIC_CODEC_PNG, // Portable Network Graphics (.png)
WIC_CODEC_TIFF, // Tagged Image File Format (.tif, .tiff)
WIC_CODEC_GIF, // Graphics Interchange Format (.gif)
WIC_CODEC_WMP, // Windows Media Photo / HD Photo / JPEG XR (.hdp, .jxr, .wdp)
WIC_CODEC_ICO, // Windows Icon (.ico)
};
REFGUID __cdecl GetWICCodec(_In_ WICCodecs codec);
IWICImagingFactory* __cdecl GetWICFactory( bool& iswic2 );
void __cdecl SetWICFactory( _In_opt_ IWICImagingFactory* pWIC);
//---------------------------------------------------------------------------------
// Direct3D 11 functions
bool __cdecl IsSupportedTexture( _In_ ID3D11Device* pDevice, _In_ const TexMetadata& metadata );
HRESULT __cdecl CreateTexture( _In_ ID3D11Device* pDevice, _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
_Outptr_ ID3D11Resource** ppResource );
HRESULT __cdecl CreateShaderResourceView( _In_ ID3D11Device* pDevice, _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
_Outptr_ ID3D11ShaderResourceView** ppSRV );
HRESULT __cdecl CreateTextureEx( _In_ ID3D11Device* pDevice, _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
_In_ D3D11_USAGE usage, _In_ unsigned int bindFlags, _In_ unsigned int cpuAccessFlags, _In_ unsigned int miscFlags, _In_ bool forceSRGB,
_Outptr_ ID3D11Resource** ppResource );
HRESULT __cdecl CreateShaderResourceViewEx( _In_ ID3D11Device* pDevice, _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
_In_ D3D11_USAGE usage, _In_ unsigned int bindFlags, _In_ unsigned int cpuAccessFlags, _In_ unsigned int miscFlags, _In_ bool forceSRGB,
_Outptr_ ID3D11ShaderResourceView** ppSRV );
HRESULT __cdecl CaptureTexture( _In_ ID3D11Device* pDevice, _In_ ID3D11DeviceContext* pContext, _In_ ID3D11Resource* pSource, _Out_ ScratchImage& result );
#include "DirectXTex.inl"
}; // namespace

View file

@ -0,0 +1,130 @@
//-------------------------------------------------------------------------------------
// DirectXTex.inl
//
// DirectX Texture Library
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// http://go.microsoft.com/fwlink/?LinkId=248926
//-------------------------------------------------------------------------------------
#pragma once
//=====================================================================================
// DXGI Format Utilities
//=====================================================================================
_Use_decl_annotations_
inline bool __cdecl IsValid( DXGI_FORMAT fmt )
{
return ( static_cast<size_t>(fmt) >= 1 && static_cast<size_t>(fmt) <= 190 );
}
_Use_decl_annotations_
inline bool __cdecl IsCompressed(DXGI_FORMAT fmt)
{
switch ( fmt )
{
case DXGI_FORMAT_BC1_TYPELESS:
case DXGI_FORMAT_BC1_UNORM:
case DXGI_FORMAT_BC1_UNORM_SRGB:
case DXGI_FORMAT_BC2_TYPELESS:
case DXGI_FORMAT_BC2_UNORM:
case DXGI_FORMAT_BC2_UNORM_SRGB:
case DXGI_FORMAT_BC3_TYPELESS:
case DXGI_FORMAT_BC3_UNORM:
case DXGI_FORMAT_BC3_UNORM_SRGB:
case DXGI_FORMAT_BC4_TYPELESS:
case DXGI_FORMAT_BC4_UNORM:
case DXGI_FORMAT_BC4_SNORM:
case DXGI_FORMAT_BC5_TYPELESS:
case DXGI_FORMAT_BC5_UNORM:
case DXGI_FORMAT_BC5_SNORM:
case DXGI_FORMAT_BC6H_TYPELESS:
case DXGI_FORMAT_BC6H_UF16:
case DXGI_FORMAT_BC6H_SF16:
case DXGI_FORMAT_BC7_TYPELESS:
case DXGI_FORMAT_BC7_UNORM:
case DXGI_FORMAT_BC7_UNORM_SRGB:
return true;
default:
return false;
}
}
_Use_decl_annotations_
inline bool __cdecl IsPalettized(DXGI_FORMAT fmt)
{
switch( fmt )
{
case DXGI_FORMAT_AI44:
case DXGI_FORMAT_IA44:
case DXGI_FORMAT_P8:
case DXGI_FORMAT_A8P8:
return true;
default:
return false;
}
}
_Use_decl_annotations_
inline bool __cdecl IsSRGB(DXGI_FORMAT fmt)
{
switch( fmt )
{
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
case DXGI_FORMAT_BC1_UNORM_SRGB:
case DXGI_FORMAT_BC2_UNORM_SRGB:
case DXGI_FORMAT_BC3_UNORM_SRGB:
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
case DXGI_FORMAT_BC7_UNORM_SRGB:
return true;
default:
return false;
}
}
//=====================================================================================
// Image I/O
//=====================================================================================
_Use_decl_annotations_
inline HRESULT __cdecl SaveToDDSMemory(const Image& image, DWORD flags, Blob& blob)
{
TexMetadata mdata;
memset( &mdata, 0, sizeof(mdata) );
mdata.width = image.width;
mdata.height = image.height;
mdata.depth = 1;
mdata.arraySize = 1;
mdata.mipLevels = 1;
mdata.format = image.format;
mdata.dimension = TEX_DIMENSION_TEXTURE2D;
return SaveToDDSMemory( &image, 1, mdata, flags, blob );
}
_Use_decl_annotations_
inline HRESULT __cdecl SaveToDDSFile(const Image& image, DWORD flags, LPCWSTR szFile)
{
TexMetadata mdata;
memset( &mdata, 0, sizeof(mdata) );
mdata.width = image.width;
mdata.height = image.height;
mdata.depth = 1;
mdata.arraySize = 1;
mdata.mipLevels = 1;
mdata.format = image.format;
mdata.dimension = TEX_DIMENSION_TEXTURE2D;
return SaveToDDSFile( &image, 1, mdata, flags, szFile );
}

View file

@ -0,0 +1,240 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|ARM">
<Configuration>Debug</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM">
<Configuration>Release</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{755AB64B-16B4-4C90-AA3B-BFF448E5A21E}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>DirectXTex</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<CLRSupport>true</CLRSupport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<CLRSupport>true</CLRSupport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<CLRSupport>true</CLRSupport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<CLRSupport>true</CLRSupport>
</PropertyGroup>
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;DIRECTXTEX_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;DIRECTXTEX_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;DIRECTXTEX_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<OpenMPSupport>true</OpenMPSupport>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>No</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;DIRECTXTEX_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<OpenMPSupport>true</OpenMPSupport>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>No</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="BC.cpp">
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</CompileAsManaged>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsManaged>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</CompileAsManaged>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged>
</ClCompile>
<ClCompile Include="BC4BC5.cpp">
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</CompileAsManaged>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsManaged>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</CompileAsManaged>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged>
</ClCompile>
<ClCompile Include="BC6HBC7.cpp">
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</CompileAsManaged>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsManaged>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</CompileAsManaged>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged>
</ClCompile>
<ClCompile Include="DirectXTexCompress.cpp">
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</CompileAsManaged>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsManaged>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</CompileAsManaged>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged>
</ClCompile>
<ClCompile Include="DirectXTexConvert.cpp">
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</CompileAsManaged>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsManaged>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</CompileAsManaged>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged>
</ClCompile>
<ClCompile Include="DirectXTexDDS.cpp">
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</CompileAsManaged>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsManaged>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</CompileAsManaged>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged>
</ClCompile>
<ClCompile Include="DirectXTexImage.cpp">
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</CompileAsManaged>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsManaged>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</CompileAsManaged>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged>
</ClCompile>
<ClCompile Include="DirectXTexMipmaps.cpp">
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</CompileAsManaged>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsManaged>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</CompileAsManaged>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged>
</ClCompile>
<ClCompile Include="DirectXTexUtil.cpp">
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</CompileAsManaged>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsManaged>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</CompileAsManaged>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged>
</ClCompile>
<ClCompile Include="wrapper.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="BC.h" />
<ClInclude Include="DDS.h" />
<ClInclude Include="DirectXTex.h" />
<ClInclude Include="DirectXTexP.h" />
<ClInclude Include="Filters.h" />
<ClInclude Include="scoped.h" />
</ItemGroup>
<ItemGroup>
<None Include="DirectXTex.inl" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Quelldateien">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Headerdateien">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Ressourcendateien">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="wrapper.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
<ClCompile Include="BC.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
<ClCompile Include="BC4BC5.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
<ClCompile Include="BC6HBC7.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
<ClCompile Include="DirectXTexCompress.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
<ClCompile Include="DirectXTexConvert.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
<ClCompile Include="DirectXTexDDS.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
<ClCompile Include="DirectXTexImage.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
<ClCompile Include="DirectXTexUtil.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
<ClCompile Include="DirectXTexMipmaps.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="BC.h">
<Filter>Headerdateien</Filter>
</ClInclude>
<ClInclude Include="DDS.h">
<Filter>Headerdateien</Filter>
</ClInclude>
<ClInclude Include="DirectXTex.h">
<Filter>Headerdateien</Filter>
</ClInclude>
<ClInclude Include="DirectXTexP.h">
<Filter>Headerdateien</Filter>
</ClInclude>
<ClInclude Include="Filters.h">
<Filter>Headerdateien</Filter>
</ClInclude>
<ClInclude Include="scoped.h">
<Filter>Headerdateien</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="DirectXTex.inl">
<Filter>Headerdateien</Filter>
</None>
</ItemGroup>
</Project>

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>

View file

@ -0,0 +1,810 @@
//-------------------------------------------------------------------------------------
// DirectXTexCompress.cpp
//
// DirectX Texture Library - Texture compression
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// http://go.microsoft.com/fwlink/?LinkId=248926
//-------------------------------------------------------------------------------------
#include "directxtexp.h"
#ifdef _OPENMP
#include <omp.h>
#pragma warning(disable : 4616 6993)
#endif
#include "bc.h"
namespace DirectX
{
inline static DWORD _GetBCFlags( _In_ DWORD compress )
{
static_assert( TEX_COMPRESS_RGB_DITHER == BC_FLAGS_DITHER_RGB, "TEX_COMPRESS_* flags should match BC_FLAGS_*" );
static_assert( TEX_COMPRESS_A_DITHER == BC_FLAGS_DITHER_A, "TEX_COMPRESS_* flags should match BC_FLAGS_*" );
static_assert( TEX_COMPRESS_DITHER == (BC_FLAGS_DITHER_RGB | BC_FLAGS_DITHER_A), "TEX_COMPRESS_* flags should match BC_FLAGS_*" );
static_assert( TEX_COMPRESS_UNIFORM == BC_FLAGS_UNIFORM, "TEX_COMPRESS_* flags should match BC_FLAGS_*" );
static_assert( TEX_COMPRESS_BC7_USE_3SUBSETS == BC_FLAGS_USE_3SUBSETS, "TEX_COMPRESS_* flags should match BC_FLAGS_*" );
return ( compress & (BC_FLAGS_DITHER_RGB|BC_FLAGS_DITHER_A|BC_FLAGS_UNIFORM|BC_FLAGS_USE_3SUBSETS) );
}
inline static DWORD _GetSRGBFlags( _In_ DWORD compress )
{
static_assert( TEX_COMPRESS_SRGB_IN == TEX_FILTER_SRGB_IN, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*" );
static_assert( TEX_COMPRESS_SRGB_OUT == TEX_FILTER_SRGB_OUT, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*" );
static_assert( TEX_COMPRESS_SRGB == TEX_FILTER_SRGB, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*" );
return ( compress & TEX_COMPRESS_SRGB );
}
inline static bool _DetermineEncoderSettings( _In_ DXGI_FORMAT format, _Out_ BC_ENCODE& pfEncode, _Out_ size_t& blocksize, _Out_ DWORD& cflags )
{
switch(format)
{
case DXGI_FORMAT_BC1_UNORM:
case DXGI_FORMAT_BC1_UNORM_SRGB: pfEncode = nullptr; blocksize = 8; cflags = 0; break;
case DXGI_FORMAT_BC2_UNORM:
case DXGI_FORMAT_BC2_UNORM_SRGB: pfEncode = D3DXEncodeBC2; blocksize = 16; cflags = 0; break;
case DXGI_FORMAT_BC3_UNORM:
case DXGI_FORMAT_BC3_UNORM_SRGB: pfEncode = D3DXEncodeBC3; blocksize = 16; cflags = 0; break;
case DXGI_FORMAT_BC4_UNORM: pfEncode = D3DXEncodeBC4U; blocksize = 8; cflags = TEX_FILTER_RGB_COPY_RED; break;
case DXGI_FORMAT_BC4_SNORM: pfEncode = D3DXEncodeBC4S; blocksize = 8; cflags = TEX_FILTER_RGB_COPY_RED; break;
case DXGI_FORMAT_BC5_UNORM: pfEncode = D3DXEncodeBC5U; blocksize = 16; cflags = TEX_FILTER_RGB_COPY_RED | TEX_FILTER_RGB_COPY_GREEN; break;
case DXGI_FORMAT_BC5_SNORM: pfEncode = D3DXEncodeBC5S; blocksize = 16; cflags = TEX_FILTER_RGB_COPY_RED | TEX_FILTER_RGB_COPY_GREEN; break;
case DXGI_FORMAT_BC6H_UF16: pfEncode = D3DXEncodeBC6HU; blocksize = 16; cflags = 0; break;
case DXGI_FORMAT_BC6H_SF16: pfEncode = D3DXEncodeBC6HS; blocksize = 16; cflags = 0; break;
case DXGI_FORMAT_BC7_UNORM:
case DXGI_FORMAT_BC7_UNORM_SRGB: pfEncode = D3DXEncodeBC7; blocksize = 16; cflags = 0; break;
default: pfEncode = nullptr; blocksize = 0; cflags = 0; return false;
}
return true;
}
//-------------------------------------------------------------------------------------
static HRESULT _CompressBC( _In_ const Image& image, _In_ const Image& result, _In_ DWORD bcflags,
_In_ DWORD srgb, _In_ float alphaRef )
{
if ( !image.pixels || !result.pixels )
return E_POINTER;
assert( image.width == result.width );
assert( image.height == result.height );
const DXGI_FORMAT format = image.format;
size_t sbpp = BitsPerPixel( format );
if ( !sbpp )
return E_FAIL;
if ( sbpp < 8 )
{
// We don't support compressing from monochrome (DXGI_FORMAT_R1_UNORM)
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
}
// Round to bytes
sbpp = ( sbpp + 7 ) / 8;
uint8_t *pDest = result.pixels;
// Determine BC format encoder
BC_ENCODE pfEncode;
size_t blocksize;
DWORD cflags;
if ( !_DetermineEncoderSettings( result.format, pfEncode, blocksize, cflags ) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
XMVECTOR temp[16];
const uint8_t *pSrc = image.pixels;
const size_t rowPitch = image.rowPitch;
for( size_t h=0; h < image.height; h += 4 )
{
const uint8_t *sptr = pSrc;
uint8_t* dptr = pDest;
size_t ph = std::min<size_t>( 4, image.height - h );
size_t w = 0;
for( size_t count = 0; (count < result.rowPitch) && (w < image.width); count += blocksize, w += 4 )
{
size_t pw = std::min<size_t>( 4, image.width - w );
assert( pw > 0 && ph > 0 );
if ( !_LoadScanline( &temp[0], pw, sptr, rowPitch, format ) )
return E_FAIL;
if ( ph > 1 )
{
if ( !_LoadScanline( &temp[4], pw, sptr + rowPitch, rowPitch, format ) )
return E_FAIL;
if ( ph > 2 )
{
if ( !_LoadScanline( &temp[8], pw, sptr + rowPitch*2, rowPitch, format ) )
return E_FAIL;
if ( ph > 3 )
{
if ( !_LoadScanline( &temp[12], pw, sptr + rowPitch*3, rowPitch, format ) )
return E_FAIL;
}
}
}
if ( pw != 4 || ph != 4 )
{
// Replicate pixels for partial block
static const size_t uSrc[] = { 0, 0, 0, 1 };
if ( pw < 4 )
{
for( size_t t = 0; t < ph && t < 4; ++t )
{
for( size_t s = pw; s < 4; ++s )
{
#pragma prefast(suppress: 26000, "PREFAST false positive")
temp[ (t << 2) | s ] = temp[ (t << 2) | uSrc[s] ];
}
}
}
if ( ph < 4 )
{
for( size_t t = ph; t < 4; ++t )
{
for( size_t s = 0; s < 4; ++s )
{
#pragma prefast(suppress: 26000, "PREFAST false positive")
temp[ (t << 2) | s ] = temp[ (uSrc[t] << 2) | s ];
}
}
}
}
_ConvertScanline( temp, 16, result.format, format, cflags | srgb );
if ( pfEncode )
pfEncode( dptr, temp, bcflags );
else
D3DXEncodeBC1( dptr, temp, alphaRef, bcflags );
sptr += sbpp*4;
dptr += blocksize;
}
pSrc += rowPitch*4;
pDest += result.rowPitch;
}
return S_OK;
}
//-------------------------------------------------------------------------------------
#ifdef _OPENMP
static HRESULT _CompressBC_Parallel( _In_ const Image& image, _In_ const Image& result, _In_ DWORD bcflags,
_In_ DWORD srgb, _In_ float alphaRef )
{
if ( !image.pixels || !result.pixels )
return E_POINTER;
assert( image.width == result.width );
assert( image.height == result.height );
const DXGI_FORMAT format = image.format;
size_t sbpp = BitsPerPixel( format );
if ( !sbpp )
return E_FAIL;
if ( sbpp < 8 )
{
// We don't support compressing from monochrome (DXGI_FORMAT_R1_UNORM)
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
}
// Round to bytes
sbpp = ( sbpp + 7 ) / 8;
// Determine BC format encoder
BC_ENCODE pfEncode;
size_t blocksize;
DWORD cflags;
if ( !_DetermineEncoderSettings( result.format, pfEncode, blocksize, cflags ) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
// Refactored version of loop to support parallel independance
const size_t nBlocks = std::max<size_t>(1, (image.width + 3) / 4 ) * std::max<size_t>(1, (image.height + 3) / 4 );
bool fail = false;
#pragma omp parallel for
for( int nb=0; nb < static_cast<int>( nBlocks ); ++nb )
{
const size_t nbWidth = std::max<size_t>(1, (image.width + 3) / 4 );
const size_t y = nb / nbWidth;
const size_t x = nb - (y*nbWidth);
assert( x < image.width && y < image.height );
size_t rowPitch = image.rowPitch;
const uint8_t *pSrc = image.pixels + (y*4*rowPitch) + (x*4*sbpp);
uint8_t *pDest = result.pixels + (nb*blocksize);
size_t ph = std::min<size_t>( 4, image.height - y );
size_t pw = std::min<size_t>( 4, image.width - x );
assert( pw > 0 && ph > 0 );
XMVECTOR temp[16];
if ( !_LoadScanline( &temp[0], pw, pSrc, rowPitch, format ) )
fail = true;
if ( ph > 1 )
{
if ( !_LoadScanline( &temp[4], pw, pSrc + rowPitch, rowPitch, format ) )
fail = true;
if ( ph > 2 )
{
if ( !_LoadScanline( &temp[8], pw, pSrc + rowPitch*2, rowPitch, format ) )
fail = true;
if ( ph > 3 )
{
if ( !_LoadScanline( &temp[12], pw, pSrc + rowPitch*3, rowPitch, format ) )
fail = true;
}
}
}
if ( pw != 4 || ph != 4 )
{
// Replicate pixels for partial block
static const size_t uSrc[] = { 0, 0, 0, 1 };
if ( pw < 4 )
{
for( size_t t = 0; t < ph && t < 4; ++t )
{
for( size_t s = pw; s < 4; ++s )
{
temp[ (t << 2) | s ] = temp[ (t << 2) | uSrc[s] ];
}
}
}
if ( ph < 4 )
{
for( size_t t = ph; t < 4; ++t )
{
for( size_t s = 0; s < 4; ++s )
{
temp[ (t << 2) | s ] = temp[ (uSrc[t] << 2) | s ];
}
}
}
}
_ConvertScanline( temp, 16, result.format, format, cflags | srgb );
if ( pfEncode )
pfEncode( pDest, temp, bcflags );
else
D3DXEncodeBC1( pDest, temp, alphaRef, bcflags );
}
return (fail) ? E_FAIL : S_OK;
}
#endif // _OPENMP
//-------------------------------------------------------------------------------------
static DXGI_FORMAT _DefaultDecompress( _In_ DXGI_FORMAT format )
{
switch( format )
{
case DXGI_FORMAT_BC1_TYPELESS:
case DXGI_FORMAT_BC1_UNORM:
case DXGI_FORMAT_BC2_TYPELESS:
case DXGI_FORMAT_BC2_UNORM:
case DXGI_FORMAT_BC3_TYPELESS:
case DXGI_FORMAT_BC3_UNORM:
case DXGI_FORMAT_BC7_TYPELESS:
case DXGI_FORMAT_BC7_UNORM:
return DXGI_FORMAT_R8G8B8A8_UNORM;
case DXGI_FORMAT_BC1_UNORM_SRGB:
case DXGI_FORMAT_BC2_UNORM_SRGB:
case DXGI_FORMAT_BC3_UNORM_SRGB:
case DXGI_FORMAT_BC7_UNORM_SRGB:
return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
case DXGI_FORMAT_BC4_TYPELESS:
case DXGI_FORMAT_BC4_UNORM:
return DXGI_FORMAT_R8_UNORM;
case DXGI_FORMAT_BC4_SNORM:
return DXGI_FORMAT_R8_SNORM;
case DXGI_FORMAT_BC5_TYPELESS:
case DXGI_FORMAT_BC5_UNORM:
return DXGI_FORMAT_R8G8_UNORM;
case DXGI_FORMAT_BC5_SNORM:
return DXGI_FORMAT_R8G8_SNORM;
case DXGI_FORMAT_BC6H_TYPELESS:
case DXGI_FORMAT_BC6H_UF16:
case DXGI_FORMAT_BC6H_SF16:
// We could use DXGI_FORMAT_R32G32B32_FLOAT here since BC6H is always Alpha 1.0,
// but this format is more supported by viewers
return DXGI_FORMAT_R32G32B32A32_FLOAT;
default:
return DXGI_FORMAT_UNKNOWN;
}
}
//-------------------------------------------------------------------------------------
static HRESULT _DecompressBC( _In_ const Image& cImage, _In_ const Image& result )
{
if ( !cImage.pixels || !result.pixels )
return E_POINTER;
assert( cImage.width == result.width );
assert( cImage.height == result.height );
const DXGI_FORMAT format = result.format;
size_t dbpp = BitsPerPixel( format );
if ( !dbpp )
return E_FAIL;
if ( dbpp < 8 )
{
// We don't support decompressing to monochrome (DXGI_FORMAT_R1_UNORM)
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
}
// Round to bytes
dbpp = ( dbpp + 7 ) / 8;
uint8_t *pDest = result.pixels;
if ( !pDest )
return E_POINTER;
// Promote "typeless" BC formats
DXGI_FORMAT cformat;
switch( cImage.format )
{
case DXGI_FORMAT_BC1_TYPELESS: cformat = DXGI_FORMAT_BC1_UNORM; break;
case DXGI_FORMAT_BC2_TYPELESS: cformat = DXGI_FORMAT_BC2_UNORM; break;
case DXGI_FORMAT_BC3_TYPELESS: cformat = DXGI_FORMAT_BC3_UNORM; break;
case DXGI_FORMAT_BC4_TYPELESS: cformat = DXGI_FORMAT_BC4_UNORM; break;
case DXGI_FORMAT_BC5_TYPELESS: cformat = DXGI_FORMAT_BC5_UNORM; break;
case DXGI_FORMAT_BC6H_TYPELESS: cformat = DXGI_FORMAT_BC6H_UF16; break;
case DXGI_FORMAT_BC7_TYPELESS: cformat = DXGI_FORMAT_BC7_UNORM; break;
default: cformat = cImage.format; break;
}
// Determine BC format decoder
BC_DECODE pfDecode;
size_t sbpp;
switch(cformat)
{
case DXGI_FORMAT_BC1_UNORM:
case DXGI_FORMAT_BC1_UNORM_SRGB: pfDecode = D3DXDecodeBC1; sbpp = 8; break;
case DXGI_FORMAT_BC2_UNORM:
case DXGI_FORMAT_BC2_UNORM_SRGB: pfDecode = D3DXDecodeBC2; sbpp = 16; break;
case DXGI_FORMAT_BC3_UNORM:
case DXGI_FORMAT_BC3_UNORM_SRGB: pfDecode = D3DXDecodeBC3; sbpp = 16; break;
case DXGI_FORMAT_BC4_UNORM: pfDecode = D3DXDecodeBC4U; sbpp = 8; break;
case DXGI_FORMAT_BC4_SNORM: pfDecode = D3DXDecodeBC4S; sbpp = 8; break;
case DXGI_FORMAT_BC5_UNORM: pfDecode = D3DXDecodeBC5U; sbpp = 16; break;
case DXGI_FORMAT_BC5_SNORM: pfDecode = D3DXDecodeBC5S; sbpp = 16; break;
case DXGI_FORMAT_BC6H_UF16: pfDecode = D3DXDecodeBC6HU; sbpp = 16; break;
case DXGI_FORMAT_BC6H_SF16: pfDecode = D3DXDecodeBC6HS; sbpp = 16; break;
case DXGI_FORMAT_BC7_UNORM:
case DXGI_FORMAT_BC7_UNORM_SRGB: pfDecode = D3DXDecodeBC7; sbpp = 16; break;
default:
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
}
XMVECTOR temp[16];
const uint8_t *pSrc = cImage.pixels;
const size_t rowPitch = result.rowPitch;
for( size_t h=0; h < cImage.height; h += 4 )
{
const uint8_t *sptr = pSrc;
uint8_t* dptr = pDest;
size_t ph = std::min<size_t>( 4, cImage.height - h );
size_t w = 0;
for( size_t count = 0; (count < cImage.rowPitch) && (w < cImage.width); count += sbpp, w += 4 )
{
pfDecode( temp, sptr );
_ConvertScanline( temp, 16, format, cformat, 0 );
size_t pw = std::min<size_t>( 4, cImage.width - w );
assert( pw > 0 && ph > 0 );
if ( !_StoreScanline( dptr, rowPitch, format, &temp[0], pw ) )
return E_FAIL;
if ( ph > 1 )
{
if ( !_StoreScanline( dptr + rowPitch, rowPitch, format, &temp[4], pw ) )
return E_FAIL;
if ( ph > 2 )
{
if ( !_StoreScanline( dptr + rowPitch*2, rowPitch, format, &temp[8], pw ) )
return E_FAIL;
if ( ph > 3 )
{
if ( !_StoreScanline( dptr + rowPitch*3, rowPitch, format, &temp[12], pw ) )
return E_FAIL;
}
}
}
sptr += sbpp;
dptr += dbpp*4;
}
pSrc += cImage.rowPitch;
pDest += rowPitch*4;
}
return S_OK;
}
//-------------------------------------------------------------------------------------
bool _IsAlphaAllOpaqueBC( _In_ const Image& cImage )
{
if ( !cImage.pixels )
return false;
// Promote "typeless" BC formats
DXGI_FORMAT cformat;
switch( cImage.format )
{
case DXGI_FORMAT_BC1_TYPELESS: cformat = DXGI_FORMAT_BC1_UNORM; break;
case DXGI_FORMAT_BC2_TYPELESS: cformat = DXGI_FORMAT_BC2_UNORM; break;
case DXGI_FORMAT_BC3_TYPELESS: cformat = DXGI_FORMAT_BC3_UNORM; break;
case DXGI_FORMAT_BC7_TYPELESS: cformat = DXGI_FORMAT_BC7_UNORM; break;
default: cformat = cImage.format; break;
}
// Determine BC format decoder
BC_DECODE pfDecode;
size_t sbpp;
switch(cformat)
{
case DXGI_FORMAT_BC1_UNORM:
case DXGI_FORMAT_BC1_UNORM_SRGB: pfDecode = D3DXDecodeBC1; sbpp = 8; break;
case DXGI_FORMAT_BC2_UNORM:
case DXGI_FORMAT_BC2_UNORM_SRGB: pfDecode = D3DXDecodeBC2; sbpp = 16; break;
case DXGI_FORMAT_BC3_UNORM:
case DXGI_FORMAT_BC3_UNORM_SRGB: pfDecode = D3DXDecodeBC3; sbpp = 16; break;
case DXGI_FORMAT_BC7_UNORM:
case DXGI_FORMAT_BC7_UNORM_SRGB: pfDecode = D3DXDecodeBC7; sbpp = 16; break;
default:
// BC4, BC5, and BC6 don't have alpha channels
return false;
}
// Scan blocks for non-opaque alpha
static const XMVECTORF32 threshold = { 0.99f, 0.99f, 0.99f, 0.99f };
XMVECTOR temp[16];
const uint8_t *pPixels = cImage.pixels;
for( size_t h = 0; h < cImage.height; h += 4 )
{
const uint8_t *ptr = pPixels;
size_t ph = std::min<size_t>( 4, cImage.height - h );
size_t w = 0;
for( size_t count = 0; (count < cImage.rowPitch) && (w < cImage.width); count += sbpp, w += 4 )
{
pfDecode( temp, ptr );
size_t pw = std::min<size_t>( 4, cImage.width - w );
assert( pw > 0 && ph > 0 );
if ( pw == 4 && ph == 4 )
{
// Full blocks
for( size_t j = 0; j < 16; ++j )
{
XMVECTOR alpha = XMVectorSplatW( temp[j] );
if ( XMVector4Less( alpha, threshold ) )
return false;
}
}
else
{
// Handle partial blocks
for( size_t y = 0; y < ph; ++y )
{
for( size_t x = 0; x < pw; ++x )
{
XMVECTOR alpha = XMVectorSplatW( temp[ y * 4 + x ] );
if ( XMVector4Less( alpha, threshold ) )
return false;
}
}
}
ptr += sbpp;
}
pPixels += cImage.rowPitch;
}
return true;
}
//=====================================================================================
// Entry-points
//=====================================================================================
//-------------------------------------------------------------------------------------
// Compression
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT Compress( const Image& srcImage, DXGI_FORMAT format, DWORD compress, float alphaRef, ScratchImage& image )
{
if ( IsCompressed(srcImage.format) || !IsCompressed(format) )
return E_INVALIDARG;
if ( IsTypeless(format)
|| IsTypeless(srcImage.format) || IsPlanar(srcImage.format) || IsPalettized(srcImage.format) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
// Create compressed image
HRESULT hr = image.Initialize2D( format, srcImage.width, srcImage.height, 1, 1 );
if ( FAILED(hr) )
return hr;
const Image *img = image.GetImage( 0, 0, 0 );
if ( !img )
{
image.Release();
return E_POINTER;
}
// Compress single image
if (compress & TEX_COMPRESS_PARALLEL)
{
#ifndef _OPENMP
return E_NOTIMPL;
#else
hr = _CompressBC_Parallel( srcImage, *img, _GetBCFlags( compress ), _GetSRGBFlags( compress ), alphaRef );
#endif // _OPENMP
}
else
{
hr = _CompressBC( srcImage, *img, _GetBCFlags( compress ), _GetSRGBFlags( compress ), alphaRef );
}
if ( FAILED(hr) )
image.Release();
return hr;
}
_Use_decl_annotations_
HRESULT Compress( const Image* srcImages, size_t nimages, const TexMetadata& metadata,
DXGI_FORMAT format, DWORD compress, float alphaRef, ScratchImage& cImages )
{
if ( !srcImages || !nimages )
return E_INVALIDARG;
if ( IsCompressed(metadata.format) || !IsCompressed(format) )
return E_INVALIDARG;
if ( IsTypeless(format)
|| IsTypeless(metadata.format) || IsPlanar(metadata.format) || IsPalettized(metadata.format) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
cImages.Release();
TexMetadata mdata2 = metadata;
mdata2.format = format;
HRESULT hr = cImages.Initialize( mdata2 );
if ( FAILED(hr) )
return hr;
if ( nimages != cImages.GetImageCount() )
{
cImages.Release();
return E_FAIL;
}
const Image* dest = cImages.GetImages();
if ( !dest )
{
cImages.Release();
return E_POINTER;
}
for( size_t index=0; index < nimages; ++index )
{
assert( dest[ index ].format == format );
const Image& src = srcImages[ index ];
if ( src.width != dest[ index ].width || src.height != dest[ index ].height )
{
cImages.Release();
return E_FAIL;
}
if ( (compress & TEX_COMPRESS_PARALLEL) )
{
#ifndef _OPENMP
return E_NOTIMPL;
#else
if ( compress & TEX_COMPRESS_PARALLEL )
{
hr = _CompressBC_Parallel( src, dest[ index ], _GetBCFlags( compress ), _GetSRGBFlags( compress ), alphaRef );
if ( FAILED(hr) )
{
cImages.Release();
return hr;
}
}
#endif // _OPENMP
}
else
{
hr = _CompressBC( src, dest[ index ], _GetBCFlags( compress ), _GetSRGBFlags( compress ), alphaRef );
if ( FAILED(hr) )
{
cImages.Release();
return hr;
}
}
}
return S_OK;
}
//-------------------------------------------------------------------------------------
// Decompression
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT Decompress( const Image& cImage, DXGI_FORMAT format, ScratchImage& image )
{
if ( !IsCompressed(cImage.format) || IsCompressed(format) )
return E_INVALIDARG;
if ( format == DXGI_FORMAT_UNKNOWN )
{
// Pick a default decompressed format based on BC input format
format = _DefaultDecompress( cImage.format );
if ( format == DXGI_FORMAT_UNKNOWN )
{
// Input is not a compressed format
return E_INVALIDARG;
}
}
else
{
if ( !IsValid(format) )
return E_INVALIDARG;
if ( IsTypeless(format) || IsPlanar(format) || IsPalettized(format) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
}
// Create decompressed image
HRESULT hr = image.Initialize2D( format, cImage.width, cImage.height, 1, 1 );
if ( FAILED(hr) )
return hr;
const Image *img = image.GetImage( 0, 0, 0 );
if ( !img )
{
image.Release();
return E_POINTER;
}
// Decompress single image
hr = _DecompressBC( cImage, *img );
if ( FAILED(hr) )
image.Release();
return hr;
}
_Use_decl_annotations_
HRESULT Decompress( const Image* cImages, size_t nimages, const TexMetadata& metadata,
DXGI_FORMAT format, ScratchImage& images )
{
if ( !cImages || !nimages )
return E_INVALIDARG;
if ( !IsCompressed(metadata.format) || IsCompressed(format) )
return E_INVALIDARG;
if ( format == DXGI_FORMAT_UNKNOWN )
{
// Pick a default decompressed format based on BC input format
format = _DefaultDecompress( cImages[0].format );
if ( format == DXGI_FORMAT_UNKNOWN )
{
// Input is not a compressed format
return E_FAIL;
}
}
else
{
if ( !IsValid(format) )
return E_INVALIDARG;
if ( IsTypeless(format) || IsPlanar(format) || IsPalettized(format) )
HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
}
images.Release();
TexMetadata mdata2 = metadata;
mdata2.format = format;
HRESULT hr = images.Initialize( mdata2 );
if ( FAILED(hr) )
return hr;
if ( nimages != images.GetImageCount() )
{
images.Release();
return E_FAIL;
}
const Image* dest = images.GetImages();
if ( !dest )
{
images.Release();
return E_POINTER;
}
for( size_t index=0; index < nimages; ++index )
{
assert( dest[ index ].format == format );
const Image& src = cImages[ index ];
if ( !IsCompressed( src.format ) )
{
images.Release();
return E_FAIL;
}
if ( src.width != dest[ index ].width || src.height != dest[ index ].height )
{
images.Release();
return E_FAIL;
}
hr = _DecompressBC( src, dest[ index ] );
if ( FAILED(hr) )
{
images.Release();
return hr;
}
}
return S_OK;
}
}; // namespace

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,794 @@
//-------------------------------------------------------------------------------------
// DirectXTexImage.cpp
//
// DirectX Texture Library - Image container
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// http://go.microsoft.com/fwlink/?LinkId=248926
//-------------------------------------------------------------------------------------
#include "directxtexp.h"
namespace DirectX
{
extern bool _CalculateMipLevels( _In_ size_t width, _In_ size_t height, _Inout_ size_t& mipLevels );
extern bool _CalculateMipLevels3D( _In_ size_t width, _In_ size_t height, _In_ size_t depth, _Inout_ size_t& mipLevels );
extern bool _IsAlphaAllOpaqueBC( _In_ const Image& cImage );
//-------------------------------------------------------------------------------------
// Determines number of image array entries and pixel size
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
void _DetermineImageArray( const TexMetadata& metadata, DWORD cpFlags,
size_t& nImages, size_t& pixelSize )
{
assert( metadata.width > 0 && metadata.height > 0 && metadata.depth > 0 );
assert( metadata.arraySize > 0 );
assert( metadata.mipLevels > 0 );
size_t _pixelSize = 0;
size_t _nimages = 0;
switch( metadata.dimension )
{
case TEX_DIMENSION_TEXTURE1D:
case TEX_DIMENSION_TEXTURE2D:
for( size_t item = 0; item < metadata.arraySize; ++item )
{
size_t w = metadata.width;
size_t h = metadata.height;
for( size_t level=0; level < metadata.mipLevels; ++level )
{
size_t rowPitch, slicePitch;
ComputePitch( metadata.format, w, h, rowPitch, slicePitch, cpFlags );
_pixelSize += slicePitch;
++_nimages;
if ( h > 1 )
h >>= 1;
if ( w > 1 )
w >>= 1;
}
}
break;
case TEX_DIMENSION_TEXTURE3D:
{
size_t w = metadata.width;
size_t h = metadata.height;
size_t d = metadata.depth;
for( size_t level=0; level < metadata.mipLevels; ++level )
{
size_t rowPitch, slicePitch;
ComputePitch( metadata.format, w, h, rowPitch, slicePitch, cpFlags );
for( size_t slice=0; slice < d; ++slice )
{
_pixelSize += slicePitch;
++_nimages;
}
if ( h > 1 )
h >>= 1;
if ( w > 1 )
w >>= 1;
if ( d > 1 )
d >>= 1;
}
}
break;
default:
assert( false );
break;
}
nImages = _nimages;
pixelSize = _pixelSize;
}
//-------------------------------------------------------------------------------------
// Fills in the image array entries
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
bool _SetupImageArray( uint8_t *pMemory, size_t pixelSize,
const TexMetadata& metadata, DWORD cpFlags,
Image* images, size_t nImages )
{
assert( pMemory );
assert( pixelSize > 0 );
assert( nImages > 0 );
if ( !images )
return false;
size_t index = 0;
uint8_t* pixels = pMemory;
const uint8_t* pEndBits = pMemory + pixelSize;
switch( metadata.dimension )
{
case TEX_DIMENSION_TEXTURE1D:
case TEX_DIMENSION_TEXTURE2D:
if (metadata.arraySize == 0 || metadata.mipLevels == 0)
{
return false;
}
for( size_t item = 0; item < metadata.arraySize; ++item )
{
size_t w = metadata.width;
size_t h = metadata.height;
for( size_t level=0; level < metadata.mipLevels; ++level )
{
if ( index >= nImages )
{
return false;
}
size_t rowPitch, slicePitch;
ComputePitch( metadata.format, w, h, rowPitch, slicePitch, cpFlags );
images[index].width = w;
images[index].height = h;
images[index].format = metadata.format;
images[index].rowPitch = rowPitch;
images[index].slicePitch = slicePitch;
images[index].pixels = pixels;
++index;
pixels += slicePitch;
if ( pixels > pEndBits )
{
return false;
}
if ( h > 1 )
h >>= 1;
if ( w > 1 )
w >>= 1;
}
}
return true;
case TEX_DIMENSION_TEXTURE3D:
{
if (metadata.mipLevels == 0 || metadata.depth == 0)
{
return false;
}
size_t w = metadata.width;
size_t h = metadata.height;
size_t d = metadata.depth;
for( size_t level=0; level < metadata.mipLevels; ++level )
{
size_t rowPitch, slicePitch;
ComputePitch( metadata.format, w, h, rowPitch, slicePitch, cpFlags );
for( size_t slice=0; slice < d; ++slice )
{
if ( index >= nImages )
{
return false;
}
// We use the same memory organization that Direct3D 11 needs for D3D11_SUBRESOURCE_DATA
// with all slices of a given miplevel being continuous in memory
images[index].width = w;
images[index].height = h;
images[index].format = metadata.format;
images[index].rowPitch = rowPitch;
images[index].slicePitch = slicePitch;
images[index].pixels = pixels;
++index;
pixels += slicePitch;
if ( pixels > pEndBits )
{
return false;
}
}
if ( h > 1 )
h >>= 1;
if ( w > 1 )
w >>= 1;
if ( d > 1 )
d >>= 1;
}
}
return true;
default:
return false;
}
}
//=====================================================================================
// ScratchImage - Bitmap image container
//=====================================================================================
ScratchImage& ScratchImage::operator= (ScratchImage&& moveFrom)
{
if ( this != &moveFrom )
{
Release();
_nimages = moveFrom._nimages;
_size = moveFrom._size;
_metadata = moveFrom._metadata;
_image = moveFrom._image;
_memory = moveFrom._memory;
moveFrom._nimages = 0;
moveFrom._size = 0;
moveFrom._image = nullptr;
moveFrom._memory = nullptr;
}
return *this;
}
//-------------------------------------------------------------------------------------
// Methods
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT ScratchImage::Initialize( const TexMetadata& mdata, DWORD flags )
{
if ( !IsValid(mdata.format) )
return E_INVALIDARG;
if ( IsPalettized(mdata.format) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
size_t mipLevels = mdata.mipLevels;
switch( mdata.dimension )
{
case TEX_DIMENSION_TEXTURE1D:
if ( !mdata.width || mdata.height != 1 || mdata.depth != 1 || !mdata.arraySize )
return E_INVALIDARG;
if ( !_CalculateMipLevels(mdata.width,1,mipLevels) )
return E_INVALIDARG;
break;
case TEX_DIMENSION_TEXTURE2D:
if ( !mdata.width || !mdata.height || mdata.depth != 1 || !mdata.arraySize )
return E_INVALIDARG;
if ( mdata.IsCubemap() )
{
if ( (mdata.arraySize % 6) != 0 )
return E_INVALIDARG;
}
if ( !_CalculateMipLevels(mdata.width,mdata.height,mipLevels) )
return E_INVALIDARG;
break;
case TEX_DIMENSION_TEXTURE3D:
if ( !mdata.width || !mdata.height || !mdata.depth || mdata.arraySize != 1 )
return E_INVALIDARG;
if ( !_CalculateMipLevels3D(mdata.width,mdata.height,mdata.depth,mipLevels) )
return E_INVALIDARG;
break;
default:
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
}
Release();
_metadata.width = mdata.width;
_metadata.height = mdata.height;
_metadata.depth = mdata.depth;
_metadata.arraySize = mdata.arraySize;
_metadata.mipLevels = mipLevels;
_metadata.miscFlags = mdata.miscFlags;
_metadata.miscFlags2 = mdata.miscFlags2;
_metadata.format = mdata.format;
_metadata.dimension = mdata.dimension;
size_t pixelSize, nimages;
_DetermineImageArray( _metadata, flags, nimages, pixelSize );
_image = new (std::nothrow) Image[ nimages ];
if ( !_image )
return E_OUTOFMEMORY;
_nimages = nimages;
memset( _image, 0, sizeof(Image) * nimages );
_memory = reinterpret_cast<uint8_t*>( _aligned_malloc( pixelSize, 16 ) );
if ( !_memory )
{
Release();
return E_OUTOFMEMORY;
}
_size = pixelSize;
if ( !_SetupImageArray( _memory, pixelSize, _metadata, flags, _image, nimages ) )
{
Release();
return E_FAIL;
}
return S_OK;
}
_Use_decl_annotations_
HRESULT ScratchImage::Initialize1D( DXGI_FORMAT fmt, size_t length, size_t arraySize, size_t mipLevels, DWORD flags )
{
if ( !length || !arraySize )
return E_INVALIDARG;
// 1D is a special case of the 2D case
HRESULT hr = Initialize2D( fmt, length, 1, arraySize, mipLevels, flags );
if ( FAILED(hr) )
return hr;
_metadata.dimension = TEX_DIMENSION_TEXTURE1D;
return S_OK;
}
_Use_decl_annotations_
HRESULT ScratchImage::Initialize2D( DXGI_FORMAT fmt, size_t width, size_t height, size_t arraySize, size_t mipLevels, DWORD flags )
{
if ( !IsValid(fmt) || !width || !height || !arraySize )
return E_INVALIDARG;
if ( IsPalettized(fmt) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
if ( !_CalculateMipLevels(width,height,mipLevels) )
return E_INVALIDARG;
Release();
_metadata.width = width;
_metadata.height = height;
_metadata.depth = 1;
_metadata.arraySize = arraySize;
_metadata.mipLevels = mipLevels;
_metadata.miscFlags = 0;
_metadata.miscFlags2 = 0;
_metadata.format = fmt;
_metadata.dimension = TEX_DIMENSION_TEXTURE2D;
size_t pixelSize, nimages;
_DetermineImageArray( _metadata, flags, nimages, pixelSize );
_image = new (std::nothrow) Image[ nimages ];
if ( !_image )
return E_OUTOFMEMORY;
_nimages = nimages;
memset( _image, 0, sizeof(Image) * nimages );
_memory = reinterpret_cast<uint8_t*>( _aligned_malloc( pixelSize, 16 ) );
if ( !_memory )
{
Release();
return E_OUTOFMEMORY;
}
_size = pixelSize;
if ( !_SetupImageArray( _memory, pixelSize, _metadata, flags, _image, nimages ) )
{
Release();
return E_FAIL;
}
return S_OK;
}
_Use_decl_annotations_
HRESULT ScratchImage::Initialize3D( DXGI_FORMAT fmt, size_t width, size_t height, size_t depth, size_t mipLevels, DWORD flags )
{
if ( !IsValid(fmt) || !width || !height || !depth )
return E_INVALIDARG;
if ( IsPalettized(fmt) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
if ( !_CalculateMipLevels3D(width,height,depth,mipLevels) )
return E_INVALIDARG;
Release();
_metadata.width = width;
_metadata.height = height;
_metadata.depth = depth;
_metadata.arraySize = 1; // Direct3D 10.x/11 does not support arrays of 3D textures
_metadata.mipLevels = mipLevels;
_metadata.miscFlags = 0;
_metadata.miscFlags2 = 0;
_metadata.format = fmt;
_metadata.dimension = TEX_DIMENSION_TEXTURE3D;
size_t pixelSize, nimages;
_DetermineImageArray( _metadata, flags, nimages, pixelSize );
_image = new (std::nothrow) Image[ nimages ];
if ( !_image )
{
Release();
return E_OUTOFMEMORY;
}
_nimages = nimages;
memset( _image, 0, sizeof(Image) * nimages );
_memory = reinterpret_cast<uint8_t*>( _aligned_malloc( pixelSize, 16 ) );
if ( !_memory )
{
Release();
return E_OUTOFMEMORY;
}
_size = pixelSize;
if ( !_SetupImageArray( _memory, pixelSize, _metadata, flags, _image, nimages ) )
{
Release();
return E_FAIL;
}
return S_OK;
}
_Use_decl_annotations_
HRESULT ScratchImage::InitializeCube( DXGI_FORMAT fmt, size_t width, size_t height, size_t nCubes, size_t mipLevels, DWORD flags )
{
if ( !width || !height || !nCubes )
return E_INVALIDARG;
// A DirectX11 cubemap is just a 2D texture array that is a multiple of 6 for each cube
HRESULT hr = Initialize2D( fmt, width, height, nCubes * 6, mipLevels, flags );
if ( FAILED(hr) )
return hr;
_metadata.miscFlags |= TEX_MISC_TEXTURECUBE;
return S_OK;
}
_Use_decl_annotations_
HRESULT ScratchImage::InitializeFromImage( const Image& srcImage, bool allow1D, DWORD flags )
{
HRESULT hr = ( srcImage.height > 1 || !allow1D )
? Initialize2D( srcImage.format, srcImage.width, srcImage.height, 1, 1, flags )
: Initialize1D( srcImage.format, srcImage.width, 1, 1, flags );
if ( FAILED(hr) )
return hr;
size_t rowCount = ComputeScanlines( srcImage.format, srcImage.height );
if ( !rowCount )
return E_UNEXPECTED;
const uint8_t* sptr = reinterpret_cast<const uint8_t*>( srcImage.pixels );
if ( !sptr )
return E_POINTER;
auto dptr = reinterpret_cast<uint8_t*>( _image[0].pixels );
if ( !dptr )
return E_POINTER;
size_t spitch = srcImage.rowPitch;
size_t dpitch = _image[0].rowPitch;
size_t size = std::min<size_t>( dpitch, spitch );
for( size_t y = 0; y < rowCount; ++y )
{
memcpy_s( dptr, dpitch, sptr, size );
sptr += spitch;
dptr += dpitch;
}
return S_OK;
}
_Use_decl_annotations_
HRESULT ScratchImage::InitializeArrayFromImages( const Image* images, size_t nImages, bool allow1D, DWORD flags )
{
if ( !images || !nImages )
return E_INVALIDARG;
DXGI_FORMAT format = images[0].format;
size_t width = images[0].width;
size_t height = images[0].height;
for( size_t index=0; index < nImages; ++index )
{
if ( !images[index].pixels )
return E_POINTER;
if ( images[index].format != format || images[index].width != width || images[index].height != height )
{
// All images must be the same format, width, and height
return E_FAIL;
}
}
HRESULT hr = ( height > 1 || !allow1D )
? Initialize2D( format, width, height, nImages, 1, flags )
: Initialize1D( format, width, nImages, 1, flags );
if ( FAILED(hr) )
return hr;
size_t rowCount = ComputeScanlines( format, height );
if ( !rowCount )
return E_UNEXPECTED;
for( size_t index=0; index < nImages; ++index )
{
auto sptr = reinterpret_cast<const uint8_t*>( images[index].pixels );
if ( !sptr )
return E_POINTER;
assert( index < _nimages );
auto dptr = reinterpret_cast<uint8_t*>( _image[index].pixels );
if ( !dptr )
return E_POINTER;
size_t spitch = images[index].rowPitch;
size_t dpitch = _image[index].rowPitch;
size_t size = std::min<size_t>( dpitch, spitch );
for( size_t y = 0; y < rowCount; ++y )
{
memcpy_s( dptr, dpitch, sptr, size );
sptr += spitch;
dptr += dpitch;
}
}
return S_OK;
}
_Use_decl_annotations_
HRESULT ScratchImage::InitializeCubeFromImages( const Image* images, size_t nImages, DWORD flags )
{
if ( !images || !nImages )
return E_INVALIDARG;
// A DirectX11 cubemap is just a 2D texture array that is a multiple of 6 for each cube
if ( ( nImages % 6 ) != 0 )
return E_INVALIDARG;
HRESULT hr = InitializeArrayFromImages( images, nImages, false, flags );
if ( FAILED(hr) )
return hr;
_metadata.miscFlags |= TEX_MISC_TEXTURECUBE;
return S_OK;
}
_Use_decl_annotations_
HRESULT ScratchImage::Initialize3DFromImages( const Image* images, size_t depth, DWORD flags )
{
if ( !images || !depth )
return E_INVALIDARG;
DXGI_FORMAT format = images[0].format;
size_t width = images[0].width;
size_t height = images[0].height;
for( size_t slice=0; slice < depth; ++slice )
{
if ( !images[slice].pixels )
return E_POINTER;
if ( images[slice].format != format || images[slice].width != width || images[slice].height != height )
{
// All images must be the same format, width, and height
return E_FAIL;
}
}
HRESULT hr = Initialize3D( format, width, height, depth, 1, flags );
if ( FAILED(hr) )
return hr;
size_t rowCount = ComputeScanlines( format, height );
if ( !rowCount )
return E_UNEXPECTED;
for( size_t slice=0; slice < depth; ++slice )
{
auto sptr = reinterpret_cast<const uint8_t*>( images[slice].pixels );
if ( !sptr )
return E_POINTER;
assert( slice < _nimages );
auto dptr = reinterpret_cast<uint8_t*>( _image[slice].pixels );
if ( !dptr )
return E_POINTER;
size_t spitch = images[slice].rowPitch;
size_t dpitch = _image[slice].rowPitch;
size_t size = std::min<size_t>( dpitch, spitch );
for( size_t y = 0; y < rowCount; ++y )
{
memcpy_s( dptr, dpitch, sptr, size );
sptr += spitch;
dptr += dpitch;
}
}
return S_OK;
}
void ScratchImage::Release()
{
_nimages = 0;
_size = 0;
if ( _image )
{
delete [] _image;
_image = 0;
}
if ( _memory )
{
_aligned_free( _memory );
_memory = 0;
}
memset(&_metadata, 0, sizeof(_metadata));
}
_Use_decl_annotations_
bool ScratchImage::OverrideFormat( DXGI_FORMAT f )
{
if ( !_image )
return false;
if ( !IsValid( f ) || IsPlanar( f ) || IsPalettized( f ) )
return false;
for( size_t index = 0; index < _nimages; ++index )
{
_image[ index ].format = f;
}
_metadata.format = f;
return true;
}
_Use_decl_annotations_
const Image* ScratchImage::GetImage(size_t mip, size_t item, size_t slice) const
{
if ( mip >= _metadata.mipLevels )
return nullptr;
size_t index = 0;
switch( _metadata.dimension )
{
case TEX_DIMENSION_TEXTURE1D:
case TEX_DIMENSION_TEXTURE2D:
if ( slice > 0 )
return nullptr;
if ( item >= _metadata.arraySize )
return nullptr;
index = item*( _metadata.mipLevels ) + mip;
break;
case TEX_DIMENSION_TEXTURE3D:
if ( item > 0 )
{
// No support for arrays of volumes
return nullptr;
}
else
{
size_t d = _metadata.depth;
for( size_t level = 0; level < mip; ++level )
{
index += d;
if ( d > 1 )
d >>= 1;
}
if ( slice >= d )
return nullptr;
index += slice;
}
break;
default:
return nullptr;
}
return &_image[index];
}
bool ScratchImage::IsAlphaAllOpaque() const
{
if ( !_image )
return false;
if ( !HasAlpha( _metadata.format ) )
return true;
if ( IsCompressed( _metadata.format ) )
{
for( size_t index = 0; index < _nimages; ++index )
{
if ( !_IsAlphaAllOpaqueBC( _image[ index ] ) )
return false;
}
}
else
{
ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*_metadata.width), 16 ) ) );
if ( !scanline )
return false;
static const XMVECTORF32 threshold = { 0.99f, 0.99f, 0.99f, 0.99f };
for( size_t index = 0; index < _nimages; ++index )
{
#pragma warning( suppress : 6011 )
const Image& img = _image[ index ];
const uint8_t *pPixels = img.pixels;
assert( pPixels );
for( size_t h = 0; h < img.height; ++h )
{
if ( !_LoadScanline( scanline.get(), img.width, pPixels, img.rowPitch, img.format ) )
return false;
XMVECTOR* ptr = scanline.get();
for( size_t w = 0; w < img.width; ++w )
{
XMVECTOR alpha = XMVectorSplatW( *ptr );
if ( XMVector4Less( alpha, threshold ) )
return false;
++ptr;
}
pPixels += img.rowPitch;
}
}
}
return true;
}
}; // namespace

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,231 @@
//-------------------------------------------------------------------------------------
// DirectXTexp.h
//
// DirectX Texture Library - Private header
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// http://go.microsoft.com/fwlink/?LinkId=248926
//-------------------------------------------------------------------------------------
#pragma once
#if !defined(WIN32_LEAN_AND_MEAN)
#define WIN32_LEAN_AND_MEAN
#endif
#if !defined(NOMINMAX)
#define NOMINMAX
#endif
#ifndef _WIN32_WINNT_WIN10
#define _WIN32_WINNT_WIN10 0x0A00
#endif
#include <windows.h>
#include <directxmath.h>
#include <directxpackedvector.h>
#include <assert.h>
#include <malloc.h>
#include <memory>
#include <vector>
#include <stdlib.h>
#include <search.h>
#include <ole2.h>
#include "directxtex.h"
// VS 2010's stdint.h conflicts with intsafe.h
#pragma warning(push)
#pragma warning(disable : 4005)
#include <wincodec.h>
#include <intsafe.h>
#pragma warning(pop)
#include <wrl\client.h>
#include "scoped.h"
#define TEX_FILTER_MASK 0xF00000
#define XBOX_DXGI_FORMAT_R10G10B10_7E3_A2_FLOAT DXGI_FORMAT(116)
#define XBOX_DXGI_FORMAT_R10G10B10_6E4_A2_FLOAT DXGI_FORMAT(117)
#define XBOX_DXGI_FORMAT_D16_UNORM_S8_UINT DXGI_FORMAT(118)
#define XBOX_DXGI_FORMAT_R16_UNORM_X8_TYPELESS DXGI_FORMAT(119)
#define XBOX_DXGI_FORMAT_X16_TYPELESS_G8_UINT DXGI_FORMAT(120)
#define WIN10_DXGI_FORMAT_P208 DXGI_FORMAT(130)
#define WIN10_DXGI_FORMAT_V208 DXGI_FORMAT(131)
#define WIN10_DXGI_FORMAT_V408 DXGI_FORMAT(132)
#ifndef XBOX_DXGI_FORMAT_R10G10B10_SNORM_A2_UNORM
#define XBOX_DXGI_FORMAT_R10G10B10_SNORM_A2_UNORM DXGI_FORMAT(189)
#endif
#define XBOX_DXGI_FORMAT_R4G4_UNORM DXGI_FORMAT(190)
namespace DirectX
{
//---------------------------------------------------------------------------------
// WIC helper functions
DXGI_FORMAT __cdecl _WICToDXGI( _In_ const GUID& guid );
bool __cdecl _DXGIToWIC( _In_ DXGI_FORMAT format, _Out_ GUID& guid, _In_ bool ignoreRGBvsBGR = false );
DWORD __cdecl _CheckWICColorSpace( _In_ const GUID& sourceGUID, _In_ const GUID& targetGUID );
inline WICBitmapDitherType __cdecl _GetWICDither( _In_ DWORD flags )
{
static_assert( TEX_FILTER_DITHER == 0x10000, "TEX_FILTER_DITHER* flag values don't match mask" );
static_assert( TEX_FILTER_DITHER == WIC_FLAGS_DITHER, "TEX_FILTER_DITHER* should match WIC_FLAGS_DITHER*" );
static_assert( TEX_FILTER_DITHER_DIFFUSION == WIC_FLAGS_DITHER_DIFFUSION, "TEX_FILTER_DITHER* should match WIC_FLAGS_DITHER*" );
switch( flags & 0xF0000 )
{
case TEX_FILTER_DITHER:
return WICBitmapDitherTypeOrdered4x4;
case TEX_FILTER_DITHER_DIFFUSION:
return WICBitmapDitherTypeErrorDiffusion;
default:
return WICBitmapDitherTypeNone;
}
}
inline WICBitmapInterpolationMode __cdecl _GetWICInterp( _In_ DWORD flags )
{
static_assert( TEX_FILTER_POINT == 0x100000, "TEX_FILTER_ flag values don't match TEX_FILTER_MASK" );
static_assert( TEX_FILTER_POINT == WIC_FLAGS_FILTER_POINT, "TEX_FILTER_* flags should match WIC_FLAGS_FILTER_*" );
static_assert( TEX_FILTER_LINEAR == WIC_FLAGS_FILTER_LINEAR, "TEX_FILTER_* flags should match WIC_FLAGS_FILTER_*" );
static_assert( TEX_FILTER_CUBIC == WIC_FLAGS_FILTER_CUBIC, "TEX_FILTER_* flags should match WIC_FLAGS_FILTER_*" );
static_assert( TEX_FILTER_FANT == WIC_FLAGS_FILTER_FANT, "TEX_FILTER_* flags should match WIC_FLAGS_FILTER_*" );
switch( flags & TEX_FILTER_MASK )
{
case TEX_FILTER_POINT:
return WICBitmapInterpolationModeNearestNeighbor;
case TEX_FILTER_LINEAR:
return WICBitmapInterpolationModeLinear;
case TEX_FILTER_CUBIC:
return WICBitmapInterpolationModeCubic;
case TEX_FILTER_FANT:
default:
return WICBitmapInterpolationModeFant;
}
}
//---------------------------------------------------------------------------------
// Image helper functions
void __cdecl _DetermineImageArray( _In_ const TexMetadata& metadata, _In_ DWORD cpFlags,
_Out_ size_t& nImages, _Out_ size_t& pixelSize );
_Success_(return != false)
bool __cdecl _SetupImageArray( _In_reads_bytes_(pixelSize) uint8_t *pMemory, _In_ size_t pixelSize,
_In_ const TexMetadata& metadata, _In_ DWORD cpFlags,
_Out_writes_(nImages) Image* images, _In_ size_t nImages );
//---------------------------------------------------------------------------------
// Conversion helper functions
enum TEXP_SCANLINE_FLAGS
{
TEXP_SCANLINE_NONE = 0,
TEXP_SCANLINE_SETALPHA = 0x1, // Set alpha channel to known opaque value
TEXP_SCANLINE_LEGACY = 0x2, // Enables specific legacy format conversion cases
};
enum CONVERT_FLAGS
{
CONVF_FLOAT = 0x1,
CONVF_UNORM = 0x2,
CONVF_UINT = 0x4,
CONVF_SNORM = 0x8,
CONVF_SINT = 0x10,
CONVF_DEPTH = 0x20,
CONVF_STENCIL = 0x40,
CONVF_SHAREDEXP = 0x80,
CONVF_BGR = 0x100,
CONVF_XR = 0x200,
CONVF_PACKED = 0x400,
CONVF_BC = 0x800,
CONVF_YUV = 0x1000,
CONVF_R = 0x10000,
CONVF_G = 0x20000,
CONVF_B = 0x40000,
CONVF_A = 0x80000,
CONVF_RGB_MASK = 0x70000,
CONVF_RGBA_MASK = 0xF0000,
};
DWORD __cdecl _GetConvertFlags( _In_ DXGI_FORMAT format );
void __cdecl _CopyScanline( _When_(pDestination == pSource, _Inout_updates_bytes_(outSize))
_When_(pDestination != pSource, _Out_writes_bytes_(outSize))
LPVOID pDestination, _In_ size_t outSize,
_In_reads_bytes_(inSize) LPCVOID pSource, _In_ size_t inSize,
_In_ DXGI_FORMAT format, _In_ DWORD flags );
void __cdecl _SwizzleScanline( _When_(pDestination == pSource, _In_)
_When_(pDestination != pSource, _Out_writes_bytes_(outSize))
LPVOID pDestination, _In_ size_t outSize,
_In_reads_bytes_(inSize) LPCVOID pSource, _In_ size_t inSize,
_In_ DXGI_FORMAT format, _In_ DWORD flags );
_Success_(return != false)
bool __cdecl _ExpandScanline( _Out_writes_bytes_(outSize) LPVOID pDestination, _In_ size_t outSize,
_In_ DXGI_FORMAT outFormat,
_In_reads_bytes_(inSize) LPCVOID pSource, _In_ size_t inSize,
_In_ DXGI_FORMAT inFormat, _In_ DWORD flags );
_Success_(return != false)
bool __cdecl _LoadScanline( _Out_writes_(count) XMVECTOR* pDestination, _In_ size_t count,
_In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size, _In_ DXGI_FORMAT format );
_Success_(return != false)
bool __cdecl _LoadScanlineLinear( _Out_writes_(count) XMVECTOR* pDestination, _In_ size_t count,
_In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size, _In_ DXGI_FORMAT format, _In_ DWORD flags );
_Success_(return != false)
bool __cdecl _StoreScanline( LPVOID pDestination, _In_ size_t size, _In_ DXGI_FORMAT format,
_In_reads_(count) const XMVECTOR* pSource, _In_ size_t count, _In_ float threshold = 0 );
_Success_(return != false)
bool __cdecl _StoreScanlineLinear( LPVOID pDestination, _In_ size_t size, _In_ DXGI_FORMAT format,
_Inout_updates_all_(count) XMVECTOR* pSource, _In_ size_t count, _In_ DWORD flags, _In_ float threshold = 0 );
_Success_(return != false)
bool __cdecl _StoreScanlineDither( LPVOID pDestination, _In_ size_t size, _In_ DXGI_FORMAT format,
_Inout_updates_all_(count) XMVECTOR* pSource, _In_ size_t count, _In_ float threshold, size_t y, size_t z,
_Inout_updates_all_opt_(count+2) XMVECTOR* pDiffusionErrors );
HRESULT __cdecl _ConvertToR32G32B32A32( _In_ const Image& srcImage, _Inout_ ScratchImage& image );
HRESULT __cdecl _ConvertFromR32G32B32A32( _In_ const Image& srcImage, _In_ const Image& destImage );
HRESULT __cdecl _ConvertFromR32G32B32A32( _In_ const Image& srcImage, _In_ DXGI_FORMAT format, _Inout_ ScratchImage& image );
HRESULT __cdecl _ConvertFromR32G32B32A32( _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
_In_ DXGI_FORMAT format, _Out_ ScratchImage& result );
void __cdecl _ConvertScanline( _Inout_updates_all_(count) XMVECTOR* pBuffer, _In_ size_t count,
_In_ DXGI_FORMAT outFormat, _In_ DXGI_FORMAT inFormat, _In_ DWORD flags );
//---------------------------------------------------------------------------------
// DDS helper functions
HRESULT __cdecl _EncodeDDSHeader( _In_ const TexMetadata& metadata, DWORD flags,
_Out_writes_bytes_to_opt_(maxsize, required) LPVOID pDestination, _In_ size_t maxsize, _Out_ size_t& required );
}; // namespace

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,422 @@
//-------------------------------------------------------------------------------------
// filters.h
//
// Utility header with helpers for implementing image filters
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//-------------------------------------------------------------------------------------
#pragma once
#include <directxmath.h>
#include <directxpackedvector.h>
#include <memory>
#include "scoped.h"
namespace DirectX
{
//-------------------------------------------------------------------------------------
// Box filtering helpers
//-------------------------------------------------------------------------------------
XMGLOBALCONST XMVECTORF32 g_boxScale = { 0.25f, 0.25f, 0.25f, 0.25f };
XMGLOBALCONST XMVECTORF32 g_boxScale3D = { 0.125f, 0.125f, 0.125f, 0.125f };
#define AVERAGE4( res, p0, p1, p2, p3 ) \
{ \
XMVECTOR v = XMVectorAdd( (p0), (p1) ); \
v = XMVectorAdd( v, (p2) ); \
v = XMVectorAdd( v, (p3) ); \
res = XMVectorMultiply( v, g_boxScale ); \
}
#define AVERAGE8( res, p0, p1, p2, p3, p4, p5, p6, p7) \
{ \
XMVECTOR v = XMVectorAdd( (p0), (p1) ); \
v = XMVectorAdd( v, (p2) ); \
v = XMVectorAdd( v, (p3) ); \
v = XMVectorAdd( v, (p4) ); \
v = XMVectorAdd( v, (p5) ); \
v = XMVectorAdd( v, (p6) ); \
v = XMVectorAdd( v, (p7) ); \
res = XMVectorMultiply( v, g_boxScale3D ); \
}
//-------------------------------------------------------------------------------------
// Linear filtering helpers
//-------------------------------------------------------------------------------------
struct LinearFilter
{
size_t u0;
float weight0;
size_t u1;
float weight1;
};
inline void _CreateLinearFilter( _In_ size_t source, _In_ size_t dest, _In_ bool wrap, _Out_writes_(dest) LinearFilter* lf )
{
assert( source > 0 );
assert( dest > 0 );
assert( lf != 0 );
float scale = float(source) / float(dest);
// Mirror is the same case as clamp for linear
for( size_t u = 0; u < dest; ++u )
{
float srcB = ( float(u) + 0.5f ) * scale + 0.5f;
ptrdiff_t isrcB = ptrdiff_t(srcB);
ptrdiff_t isrcA = isrcB - 1;
if ( isrcA < 0 )
{
isrcA = ( wrap ) ? ( source - 1) : 0;
}
if ( size_t(isrcB) >= source )
{
isrcB = ( wrap ) ? 0 : ( source - 1);
}
float weight = 1.0f + float(isrcB) - srcB;
auto& entry = lf[ u ];
entry.u0 = size_t(isrcA);
entry.weight0 = weight;
entry.u1 = size_t(isrcB);
entry.weight1 = 1.0f - weight;
}
}
#define BILINEAR_INTERPOLATE( res, x, y, r0, r1 ) \
res = ( y.weight0 * ( (r0)[ x.u0 ] * x.weight0 + (r0)[ x.u1 ] * x.weight1 ) ) \
+ ( y.weight1 * ( (r1)[ x.u0 ] * x.weight0 + (r1)[ x.u1 ] * x.weight1 ) )
#define TRILINEAR_INTERPOLATE( res, x, y, z, r0, r1, r2, r3 ) \
res = ( z.weight0 * ( ( y.weight0 * ( (r0)[ x.u0 ] * x.weight0 + (r0)[ x.u1 ] * x.weight1 ) ) \
+ ( y.weight1 * ( (r1)[ x.u0 ] * x.weight0 + (r1)[ x.u1 ] * x.weight1 ) ) ) ) \
+ ( z.weight1 * ( ( y.weight0 * ( (r2)[ x.u0 ] * x.weight0 + (r2)[ x.u1 ] * x.weight1 ) ) \
+ ( y.weight1 * ( (r3)[ x.u0 ] * x.weight0 + (r3)[ x.u1 ] * x.weight1 ) ) ) )
//-------------------------------------------------------------------------------------
// Cubic filtering helpers
//-------------------------------------------------------------------------------------
XMGLOBALCONST XMVECTORF32 g_cubicThird = { 1.f/3.f, 1.f/3.f, 1.f/3.f, 1.f/3.f };
XMGLOBALCONST XMVECTORF32 g_cubicSixth = { 1.f/6.f, 1.f/6.f, 1.f/6.f, 1.f/6.f };
XMGLOBALCONST XMVECTORF32 g_cubicHalf = { 1.f/2.f, 1.f/2.f, 1.f/2.f, 1.f/2.f };
inline ptrdiff_t bounduvw( ptrdiff_t u, ptrdiff_t maxu, bool wrap, bool mirror )
{
if ( wrap )
{
if ( u < 0 )
{
u = maxu + u + 1;
}
else if ( u > maxu )
{
u = u - maxu - 1;
}
}
else if ( mirror )
{
if ( u < 0 )
{
u = ( -u ) - 1;
}
else if ( u > maxu )
{
u = maxu - (u - maxu - 1);
}
}
// Handles clamp, but also a safety factor for degenerate images for wrap/mirror
u = std::min<ptrdiff_t>( u, maxu );
u = std::max<ptrdiff_t>( u, 0 );
return u;
}
struct CubicFilter
{
size_t u0;
size_t u1;
size_t u2;
size_t u3;
float x;
};
inline void _CreateCubicFilter( _In_ size_t source, _In_ size_t dest, _In_ bool wrap, _In_ bool mirror, _Out_writes_(dest) CubicFilter* cf )
{
assert( source > 0 );
assert( dest > 0 );
assert( cf != 0 );
float scale = float(source) / float(dest);
for( size_t u = 0; u < dest; ++u )
{
float srcB = ( float(u) + 0.5f ) * scale - 0.5f;
ptrdiff_t isrcB = bounduvw( ptrdiff_t(srcB), source - 1, wrap, mirror );
ptrdiff_t isrcA = bounduvw( isrcB - 1, source - 1, wrap, mirror );
ptrdiff_t isrcC = bounduvw( isrcB + 1, source - 1, wrap, mirror );
ptrdiff_t isrcD = bounduvw( isrcB + 2, source - 1, wrap, mirror );
auto& entry = cf[ u ];
entry.u0 = size_t(isrcA);
entry.u1 = size_t(isrcB);
entry.u2 = size_t(isrcC);
entry.u3 = size_t(isrcD);
float x = srcB - float(isrcB);
entry.x = x;
}
}
#define CUBIC_INTERPOLATE( res, dx, p0, p1, p2, p3 ) \
{ \
XMVECTOR a0 = (p1); \
XMVECTOR d0 = (p0) - a0; \
XMVECTOR d2 = (p2) - a0; \
XMVECTOR d3 = (p3) - a0; \
XMVECTOR a1 = d2 - g_cubicThird*d0 - g_cubicSixth*d3; \
XMVECTOR a2 = g_cubicHalf*d0 + g_cubicHalf*d2; \
XMVECTOR a3 = g_cubicSixth*d3 - g_cubicSixth*d0 - g_cubicHalf*d2; \
XMVECTOR vdx = XMVectorReplicate( dx ); \
XMVECTOR vdx2 = vdx * vdx; \
XMVECTOR vdx3 = vdx2 * vdx; \
res = a0 + a1*vdx + a2*vdx2 + a3*vdx3; \
}
//-------------------------------------------------------------------------------------
// Triangle filtering helpers
//-------------------------------------------------------------------------------------
namespace TriangleFilter
{
struct FilterTo
{
size_t u;
float weight;
};
struct FilterFrom
{
size_t count;
size_t sizeInBytes;
FilterTo to[1]; // variable-sized array
};
struct Filter
{
size_t sizeInBytes;
size_t totalSize;
FilterFrom from[1]; // variable-sized array
};
struct TriangleRow
{
size_t remaining;
TriangleRow* next;
ScopedAlignedArrayXMVECTOR scanline;
TriangleRow() : remaining(0), next(nullptr) {}
};
static const size_t TF_FILTER_SIZE = sizeof(Filter) - sizeof(FilterFrom);
static const size_t TF_FROM_SIZE = sizeof(FilterFrom) - sizeof(FilterTo);
static const size_t TF_TO_SIZE = sizeof(FilterTo);
static const float TF_EPSILON = 0.00001f;
inline HRESULT _Create( _In_ size_t source, _In_ size_t dest, _In_ bool wrap, _Inout_ std::unique_ptr<Filter>& tf )
{
assert( source > 0 );
assert( dest > 0 );
float scale = float(dest) / float(source);
float scaleInv = 0.5f / scale;
// Determine storage required for filter and allocate memory if needed
size_t totalSize = TF_FILTER_SIZE + TF_FROM_SIZE + TF_TO_SIZE;
float repeat = (wrap) ? 1.f : 0.f;
for( size_t u = 0; u < source; ++u )
{
float src = float(u) - 0.5f;
float destMin = src * scale;
float destMax = destMin + scale;
totalSize += TF_FROM_SIZE + TF_TO_SIZE + size_t( destMax - destMin + repeat + 1.f ) * TF_TO_SIZE * 2;
}
uint8_t* pFilter = nullptr;
if ( tf )
{
// See if existing filter memory block is large enough to reuse
if ( tf->totalSize >= totalSize )
{
pFilter = reinterpret_cast<uint8_t*>( tf.get() );
}
else
{
// Need to reallocate filter memory block
tf.reset( nullptr );
}
}
if ( !tf )
{
// Allocate filter memory block
pFilter = new (std::nothrow) uint8_t[ totalSize ];
if ( !pFilter )
return E_OUTOFMEMORY;
tf.reset( reinterpret_cast<Filter*>( pFilter ) );
tf->totalSize = totalSize;
}
assert( pFilter != 0 );
// Filter setup
size_t sizeInBytes = TF_FILTER_SIZE;
size_t accumU = 0;
float accumWeight = 0.f;
for( size_t u = 0; u < source; ++u )
{
// Setup from entry
size_t sizeFrom = sizeInBytes;
auto pFrom = reinterpret_cast<FilterFrom*>( pFilter + sizeInBytes );
sizeInBytes += TF_FROM_SIZE;
if ( sizeInBytes > totalSize )
return E_FAIL;
size_t toCount = 0;
// Perform two passes to capture the influences from both sides
for( size_t j = 0; j < 2; ++j )
{
float src = float( u + j ) - 0.5f;
float destMin = src * scale;
float destMax = destMin + scale;
if ( !wrap )
{
// Clamp
if ( destMin < 0.f )
destMin = 0.f;
if ( destMax > float(dest) )
destMax = float(dest);
}
for( auto k = static_cast<ptrdiff_t>( floorf( destMin ) ); float(k) < destMax; ++k )
{
float d0 = float(k);
float d1 = d0 + 1.f;
size_t u0;
if ( k < 0 )
{
// Handle wrap
u0 = size_t( k + ptrdiff_t(dest) );
}
else if ( k >= ptrdiff_t(dest) )
{
// Handle wrap
u0 = size_t( k - ptrdiff_t(dest) );
}
else
{
u0 = size_t( k );
}
// Save previous accumulated weight (if any)
if ( u0 != accumU )
{
if ( accumWeight > TF_EPSILON )
{
auto pTo = reinterpret_cast<FilterTo*>( pFilter + sizeInBytes );
sizeInBytes += TF_TO_SIZE;
++toCount;
if ( sizeInBytes > totalSize )
return E_FAIL;
pTo->u = accumU;
pTo->weight = accumWeight;
}
accumWeight = 0.f;
accumU = u0;
}
// Clip destination
if ( d0 < destMin )
d0 = destMin;
if ( d1 > destMax )
d1 = destMax;
// Calculate average weight over destination pixel
float weight;
if ( !wrap && src < 0.f )
weight = 1.f;
else if ( !wrap && ( ( src + 1.f ) >= float(source) ) )
weight = 0.f;
else
weight = (d0 + d1) * scaleInv - src;
accumWeight += (d1 - d0) * ( j ? (1.f - weight) : weight );
}
}
// Store accumulated weight
if ( accumWeight > TF_EPSILON )
{
auto pTo = reinterpret_cast<FilterTo*>( pFilter + sizeInBytes );
sizeInBytes += TF_TO_SIZE;
++toCount;
if ( sizeInBytes > totalSize )
return E_FAIL;
pTo->u = accumU;
pTo->weight = accumWeight;
}
accumWeight = 0.f;
// Finalize from entry
pFrom->count = toCount;
pFrom->sizeInBytes = sizeInBytes - sizeFrom;
}
tf->sizeInBytes = sizeInBytes;
return S_OK;
}
}; // namespace
}; // namespace

View file

@ -0,0 +1,32 @@
//-------------------------------------------------------------------------------------
// scoped.h
//
// Utility header with helper classes for exception-safe handling of resources
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//-------------------------------------------------------------------------------------
#pragma once
#include <assert.h>
#include <memory>
#include <malloc.h>
//---------------------------------------------------------------------------------
struct aligned_deleter { void operator()(void* p) { _aligned_free(p); } };
typedef std::unique_ptr<float[], aligned_deleter> ScopedAlignedArrayFloat;
typedef std::unique_ptr<DirectX::XMVECTOR[], aligned_deleter> ScopedAlignedArrayXMVECTOR;
//---------------------------------------------------------------------------------
struct handle_closer { void operator()(HANDLE h) { assert(h != INVALID_HANDLE_VALUE); if (h) CloseHandle(h); } };
typedef public std::unique_ptr<void, handle_closer> ScopedHandle;
inline HANDLE safe_handle( HANDLE h ) { return (h == INVALID_HANDLE_VALUE) ? 0 : h; }

View file

@ -0,0 +1,274 @@
/*
Copyright(c) 2015 Neodymium
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#pragma managed
#include <vcclr.h>
#include "DirectXTex.h"
using namespace System;
using namespace System::IO;
using namespace System::Runtime::InteropServices;
namespace DirectXTex
{
public ref class ImageCompressor
{
public:
static array<Byte>^ Decompress(array<Byte>^ data, int width, int height, int format)
{
size_t rowPitch;
size_t slicePitch;
DirectX::ComputePitch((DXGI_FORMAT)format, width, height, rowPitch, slicePitch);
if (data->Length == slicePitch)
{
uint8_t *buf = new uint8_t[slicePitch];
Marshal::Copy(data, 0, (IntPtr)buf, slicePitch);
DirectX::Image inputImage;
inputImage.width = width;
inputImage.height = height;
inputImage.format = (DXGI_FORMAT)format;
inputImage.pixels = buf;
inputImage.rowPitch = rowPitch;
inputImage.slicePitch = slicePitch;
DirectX::ScratchImage outputImage;
// decompress image
DirectX::Decompress(inputImage, DXGI_FORMAT_R8G8B8A8_UNORM, outputImage);
array<Byte>^ result = gcnew array<Byte>(4 * width * height);
Marshal::Copy((IntPtr)outputImage.GetPixels(), result, 0, 4 * width * height);
delete[] buf;
return result;
}
else
{
throw gcnew Exception("Compressed image should be " + slicePitch.ToString() + " bytes");
}
}
static array<Byte>^ Compress(array<Byte>^ data, int width, int height, int format)
{
size_t rowPitch = width * 4;
size_t slicePitch = width * height * 4;
if (data->Length == slicePitch)
{
uint8_t *buf = new uint8_t[slicePitch];
Marshal::Copy(data, 0, (IntPtr)buf, slicePitch);
DirectX::Image inputImage;
inputImage.width = width;
inputImage.height = height;
inputImage.format = DXGI_FORMAT_R8G8B8A8_UNORM;
inputImage.pixels = buf;
inputImage.rowPitch = rowPitch;
inputImage.slicePitch = slicePitch;
DirectX::ScratchImage outputImage;
// compress image
DirectX::Compress(inputImage, (DXGI_FORMAT)format, 0, 1, outputImage);
size_t rowPitchOut;
size_t slicePitchOut;
DirectX::ComputePitch((DXGI_FORMAT)format, width, height, rowPitchOut, slicePitchOut);
array<Byte>^ result = gcnew array<Byte>(slicePitchOut);
Marshal::Copy((IntPtr)outputImage.GetPixels(), result, 0, slicePitchOut);
delete[] buf;
return result;
}
else
{
throw gcnew Exception("Uncompressed image should be " + slicePitch.ToString() + " bytes");
}
}
};
public ref class ImageConverter
{
public:
static array<Byte>^ Convert(array<Byte>^ data, int width, int height, int inputFormat, int outputFormat)
{
size_t inputRowPitch;
size_t inrputSlicePitch;
DirectX::ComputePitch((DXGI_FORMAT)inputFormat, width, height, inputRowPitch, inrputSlicePitch);
if (data->Length == inrputSlicePitch)
{
uint8_t *buf = new uint8_t[inrputSlicePitch];
Marshal::Copy(data, 0, (IntPtr)buf, inrputSlicePitch);
DirectX::Image inputImage;
inputImage.width = width;
inputImage.height = height;
inputImage.format = (DXGI_FORMAT)inputFormat;
inputImage.pixels = buf;
inputImage.rowPitch = inputRowPitch;
inputImage.slicePitch = inrputSlicePitch;
DirectX::ScratchImage outputImage;
// convert image
DirectX::Convert(inputImage, (DXGI_FORMAT)outputFormat, 0, 0, outputImage);
size_t outputRowPitch;
size_t outputSlicePitch;
DirectX::ComputePitch((DXGI_FORMAT)outputFormat, width, height, outputRowPitch, outputSlicePitch);
array<Byte>^ result = gcnew array<Byte>(outputSlicePitch);
Marshal::Copy((IntPtr)outputImage.GetPixels(), result, 0, outputSlicePitch);
delete[] buf;
return result;
}
else
{
throw gcnew Exception("Input image should be " + inrputSlicePitch.ToString() + " bytes");
}
}
};
public ref class ImageStruct
{
public:
property int Width;
property int Height;
//property int Stride;
property int Format;
property int MipMapLevels;
property array<Byte>^ Data;
int GetRowPitch()
{
size_t rowPitch;
size_t slicePitch;
DirectX::ComputePitch((DXGI_FORMAT)Format, Width, Height, rowPitch, slicePitch);
return rowPitch;
}
int GetSlicePitch()
{
size_t rowPitch;
size_t slicePitch;
DirectX::ComputePitch((DXGI_FORMAT)Format, Width, Height, rowPitch, slicePitch);
return slicePitch;
}
};
public ref class DDSIO
{
private:
public:
static ImageStruct^ ReadDDS(String^ fileName)
{
DirectX::TexMetadata meta;
DirectX::ScratchImage im;
pin_ptr<const wchar_t> wname = PtrToStringChars(fileName);
// load dds
HRESULT x = DirectX::LoadFromDDSFile(wname, 0, &meta, im);
ImageStruct^ result = gcnew ImageStruct();
result->MipMapLevels = im.GetImageCount();
result->Width = im.GetImage(0, 0, 0)->width;
result->Height = im.GetImage(0, 0, 0)->height;
// result->Stride = im.GetImage(0, 0, 0)->rowPitch;
result->Format = im.GetImage(0, 0, 0)->format;
result->Data = gcnew array<Byte>(im.GetPixelsSize());
Marshal::Copy((IntPtr)im.GetPixels(), result->Data, 0, im.GetPixelsSize());
return result;
}
//static ImageStruct^ ReadDDS(Stream^ stream)
//{
// DirectX::TexMetadata meta;
// DirectX::ScratchImage im;
// //pin_ptr<const wchar_t> wname = PtrToStringChars(fileName);
// HRESULT x = DirectX:::LoadFromDDSMemory(
// ImageStruct^ result = gcnew ImageStruct();
// result->mipMapLevels = im.GetImageCount();
// result->width = im.GetImage(0, 0, 0)->width;
// result->height = im.GetImage(0, 0, 0)->height;
// result->stride = im.GetImage(0, 0, 0)->rowPitch;
// result->format = im.GetImage(0, 0, 0)->format;
// result->data = gcnew array<Byte>(im.GetPixelsSize());
// Marshal::Copy((IntPtr)im.GetPixels(), result->data, 0, im.GetPixelsSize());
// return result;
//}
static void WriteDDS(String^ fileName, ImageStruct^ image)
{
uint8_t *buf = new uint8_t[image->Data->Length];
Marshal::Copy(image->Data, 0, (IntPtr)buf, image->Data->Length);
DirectX::TexMetadata meta;
meta.width = image->Width;
meta.height = image->Height;
meta.depth = 1;
meta.arraySize = 1; // ???
meta.mipLevels = image->MipMapLevels;
meta.miscFlags = 0; // ???
meta.miscFlags2 = 0; // ???
meta.format = (DXGI_FORMAT)image->Format;
meta.dimension = DirectX::TEX_DIMENSION_TEXTURE2D;
DirectX::Image *images = new DirectX::Image[image->MipMapLevels];
int div = 1;
int add = 0;
for (int i = 0; i < image->MipMapLevels; i++)
{
images[i].width = image->Width / div;
images[i].height = image->Height / div;
images[i].format = (DXGI_FORMAT)image->Format;
images[i].pixels = buf + add;
DirectX::ComputePitch(images[i].format, images[i].width, images[i].height, images[i].rowPitch, images[i].slicePitch, 0);
add += images[i].slicePitch;
div *= 2;
}
pin_ptr<const wchar_t> wname = PtrToStringChars(fileName);
// save dds
DirectX::SaveToDDSFile(images, image->MipMapLevels, meta, 0, wname);
delete[] images;
}
};
}

Binary file not shown.

File diff suppressed because it is too large Load diff

View file

@ -240,6 +240,7 @@ namespace Switch_Toolbox
public void OpenFile(string FileName, byte[] data = null, bool Compressed = false, public void OpenFile(string FileName, byte[] data = null, bool Compressed = false,
CompressionType CompType = CompressionType.None) CompressionType CompType = CompressionType.None)
{ {
Reload();
if (data == null) if (data == null)
data = File.ReadAllBytes(FileName); data = File.ReadAllBytes(FileName);
@ -278,8 +279,6 @@ namespace Switch_Toolbox
foreach (IFileFormat format in SupportedFormats) foreach (IFileFormat format in SupportedFormats)
{ {
Console.WriteLine(format.Magic.Reverse());
Console.WriteLine(Magic2);
if (format.Magic == Magic || format.Magic == Magic2 || format.Magic.Reverse() == Magic2) if (format.Magic == Magic || format.Magic == Magic2 || format.Magic.Reverse() == Magic2)
{ {

View file

@ -388,9 +388,6 @@
<Content Include="Lib\Licenses\ZSTD NET COPYRIGHT.txt"> <Content Include="Lib\Licenses\ZSTD NET COPYRIGHT.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="LZ4.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Projects\Recent\DUMMY.txt" /> <Content Include="Projects\Recent\DUMMY.txt" />
<None Include="Resources\Logo.png" /> <None Include="Resources\Logo.png" />
<Content Include="Tool.ico" /> <Content Include="Tool.ico" />

View file

@ -43,6 +43,7 @@ namespace Switch_Toolbox.Library
CONSTANT, CONSTANT,
HERMITE, HERMITE,
STEP, STEP,
STEPBOOL,
}; };
public class KeyNode : TreeNode public class KeyNode : TreeNode
@ -298,6 +299,7 @@ namespace Switch_Toolbox.Library
if (Frame == 0 && !isChild) if (Frame == 0 && !isChild)
skeleton.reset(); skeleton.reset();
foreach (object child in Children) foreach (object child in Children)
{ {
if (child is Animation) if (child is Animation)

View file

@ -8,7 +8,7 @@ using OpenTK;
namespace Switch_Toolbox.Library namespace Switch_Toolbox.Library
{ {
public class AnimationGroupNode : TreeNode public class AnimationGroupNode : TreeNodeCustom
{ {
} }
} }

View file

@ -34,7 +34,7 @@ namespace Switch_Toolbox.Library
AssimpContext Importer = new AssimpContext(); AssimpContext Importer = new AssimpContext();
scene = Importer.ImportFile(FileName, PostProcessSteps.Triangulate | PostProcessSteps.JoinIdenticalVertices scene = Importer.ImportFile(FileName, PostProcessSteps.Triangulate | PostProcessSteps.JoinIdenticalVertices
| PostProcessSteps.FlipUVs | PostProcessSteps.ValidateDataStructure | | PostProcessSteps.FlipUVs | PostProcessSteps.LimitBoneWeights |
PostProcessSteps.CalculateTangentSpace | PostProcessSteps.GenerateNormals); PostProcessSteps.CalculateTangentSpace | PostProcessSteps.GenerateNormals);
LoadMeshes(); LoadMeshes();
} }
@ -55,23 +55,17 @@ namespace Switch_Toolbox.Library
} }
} }
} }
private void BuildNode(Node node, ref Matrix4x4 rootTransform) private void BuildNode(Node parent, ref Matrix4x4 rootTransform)
{ {
Matrix4x4 trafo = node.Transform; Matrix4x4 trafo = parent.Transform;
Matrix4x4 world = trafo * rootTransform; Matrix4x4 world = trafo * rootTransform;
Matrix4 worldTK = TKMatrix(world); Matrix4 worldTK = AssimpHelper.TKMatrix(world);
if (node.HasMeshes) foreach (int index in parent.MeshIndices)
{ objects.Add(CreateGenericObject(scene.Meshes[index], index, worldTK));
foreach (int index in node.MeshIndices)
{ foreach (Node child in parent.Children)
objects.Add(CreateGenericObject(scene.Meshes[index], index, worldTK)); BuildNode(child, ref rootTransform);
}
}
for (int i = 0; i < node.ChildCount; i++)
{
BuildNode(node.Children[i], ref world);
}
} }
public void LoadMeshes() public void LoadMeshes()
{ {
@ -81,14 +75,41 @@ namespace Switch_Toolbox.Library
{ {
foreach (Material mat in scene.Materials) foreach (Material mat in scene.Materials)
{ {
Console.WriteLine(mat.Name + " TEST");
materials.Add(CreateGenericMaterial(mat)); materials.Add(CreateGenericMaterial(mat));
} }
} }
} foreach (Assimp.Animation animation in scene.Animations)
void CopyNodesWithMeshes() {
{
}
}
public Animation CreateGenericAnimation(Assimp.Animation animation)
{
Animation STanim = new Animation();
STanim.Text = animation.Name;
STanim.FrameCount = (int)animation.DurationInTicks;
//Load node animations
if (animation.HasNodeAnimations)
{
var _channels = new NodeAnimationChannel[animation.NodeAnimationChannelCount];
for (int i = 0; i < _channels.Length; i++)
{
_channels[i] = new NodeAnimationChannel();
}
}
//Load mesh animations
if (animation.HasMeshAnimations)
{
var _meshChannels = new MeshAnimationChannel[animation.MeshAnimationChannelCount];
for (int i = 0; i < _meshChannels.Length; i++)
{
_meshChannels[i] = new MeshAnimationChannel();
}
}
return STanim;
} }
public STGenericMaterial CreateGenericMaterial(Material material) public STGenericMaterial CreateGenericMaterial(Material material)
{ {
@ -459,33 +480,19 @@ namespace Switch_Toolbox.Library
vert.col = new Vector4(msh.VertexColorChannels[0][v].R, msh.VertexColorChannels[0][v].G, msh.VertexColorChannels[0][v].B, msh.VertexColorChannels[0][v].A); vert.col = new Vector4(msh.VertexColorChannels[0][v].R, msh.VertexColorChannels[0][v].G, msh.VertexColorChannels[0][v].B, msh.VertexColorChannels[0][v].A);
if (msh.HasTangentBasis) if (msh.HasTangentBasis)
vert.bitan = new Vector4(msh.BiTangents[v].X, msh.BiTangents[v].Y, msh.BiTangents[v].Z, 1); vert.bitan = new Vector4(msh.BiTangents[v].X, msh.BiTangents[v].Y, msh.BiTangents[v].Z, 1);
if (msh.HasBones)
{
foreach (Bone bn in msh.Bones)
{
}
}
vertices.Add(vert); vertices.Add(vert);
} }
if (msh.HasBones) if (msh.HasBones)
{ {
for (int i = 0; i < msh.BoneCount; i++) for (int i = 0; i < msh.BoneCount; i++)
{ {
Bone bn = msh.Bones[i]; Bone bn = msh.Bones[i];
Console.WriteLine($"Bone Info {bn.VertexWeightCount} {bn.Name}");
Vertex.Bone bone = new Vertex.Bone();
bone.Name = bn.Name;
bone.HasWeights = bn.HasVertexWeights;
if (bn.HasVertexWeights) if (bn.HasVertexWeights)
{ {
foreach (VertexWeight w in bn.VertexWeights) foreach (VertexWeight w in bn.VertexWeights)
{ {
vertices[w.VertexID].pos = Vector3.TransformPosition(vertices[w.VertexID].pos, FromMatrix( bn.OffsetMatrix)); // vertices[w.VertexID].pos = Vector3.TransformPosition(vertices[w.VertexID].pos, AssimpHelper.TKMatrix(bn.OffsetMatrix));
vertices[w.VertexID].weights.Add(w.Weight); vertices[w.VertexID].boneWeights.Add(w.Weight);
vertices[w.VertexID].boneNames.Add(bn.Name); vertices[w.VertexID].boneNames.Add(bn.Name);
} }
} }
@ -503,13 +510,6 @@ namespace Switch_Toolbox.Library
v.Z = vec.Z; v.Z = vec.Z;
return v; return v;
} }
public static OpenTK.Matrix4 TKMatrix(Assimp.Matrix4x4 input)
{
return new OpenTK.Matrix4(input.A1, input.B1, input.C1, input.D1,
input.A2, input.B2, input.C2, input.D2,
input.A3, input.B3, input.C3, input.D3,
input.A4, input.B4, input.C4, input.D4);
}
public static OpenTK.Matrix4 TKMatrix2(Assimp.Matrix4x4 matOut) public static OpenTK.Matrix4 TKMatrix2(Assimp.Matrix4x4 matOut)
{ {
var matIn = new OpenTK.Matrix4(); var matIn = new OpenTK.Matrix4();
@ -550,78 +550,11 @@ namespace Switch_Toolbox.Library
Console.WriteLine($"rotQ " + rot); Console.WriteLine($"rotQ " + rot);
Matrix4 positionMat = Matrix4.CreateTranslation(FromVector(tranlation)); Matrix4 positionMat = Matrix4.CreateTranslation(FromVector(tranlation));
Matrix4 rotQ = Matrix4.CreateFromQuaternion(TKQuaternion(rot)); Matrix4 rotQ = Matrix4.CreateFromQuaternion(AssimpHelper.TKQuaternion(rot));
Matrix4 scaleMat = Matrix4.CreateScale(FromVector(scaling)); Matrix4 scaleMat = Matrix4.CreateScale(FromVector(scaling));
Matrix4 matrixFinal = scaleMat * rotQ * positionMat; Matrix4 matrixFinal = scaleMat * rotQ * positionMat;
return matrixFinal; return matrixFinal;
} }
private OpenTK.Quaternion TKQuaternion(Assimp.Quaternion rot)
{
OpenTK.Quaternion quat = new OpenTK.Quaternion();
quat.X = rot.X;
quat.Y = rot.Y;
quat.Z = rot.Z;
quat.W = rot.W;
return quat;
}
private Matrix4 FromMatrix(Matrix4x4 mat)
{
Matrix4 m = new Matrix4();
m.M11 = mat.A1;
m.M12 = mat.A2;
m.M13 = mat.A3;
m.M14 = mat.A4;
m.M21 = mat.B1;
m.M22 = mat.B2;
m.M23 = mat.B3;
m.M24 = mat.B4;
m.M31 = mat.C1;
m.M32 = mat.C2;
m.M33 = mat.C3;
m.M34 = mat.C4;
m.M41 = mat.D1;
m.M42 = mat.D2;
m.M43 = mat.D3;
m.M44 = mat.D4;
return m;
}
public static Vector3 ToEulerAngles(Assimp.Quaternion q)
{
float PI = (float)Math.PI;
// Store the Euler angles in radians
Vector3 pitchYawRoll = new Vector3();
double sqw = q.W * q.W;
double sqx = q.X * q.X;
double sqy = q.Y * q.Y;
double sqz = q.Z * q.Z;
// If quaternion is normalised the unit is one, otherwise it is the correction factor
double unit = sqx + sqy + sqz + sqw;
double test = q.X * q.Y + q.Z * q.W;
if (test > 0.499f * unit)
{
// Singularity at north pole
pitchYawRoll.Y = 2f * (float)Math.Atan2(q.X, q.W); // Yaw
pitchYawRoll.X = PI * 0.5f; // Pitch
pitchYawRoll.Z = 0f; // Roll
return pitchYawRoll;
}
else if (test < -0.499f * unit)
{
// Singularity at south pole
pitchYawRoll.Y = -2f * (float)Math.Atan2(q.X, q.W); // Yaw
pitchYawRoll.X = -PI * 0.5f; // Pitch
pitchYawRoll.Z = 0f; // Roll
return pitchYawRoll;
}
pitchYawRoll.Y = (float)Math.Atan2(2 * q.Y * q.W - 2 * q.X * q.Z, sqx - sqy - sqz + sqw); // Yaw
pitchYawRoll.X = (float)Math.Asin(2 * test / unit); // Pitch
pitchYawRoll.Z = (float)Math.Atan2(2 * q.X * q.W - 2 * q.Y * q.Z, -sqx + sqy - sqz + sqw); // Roll
return pitchYawRoll;
}
} }
} }

View file

@ -4,10 +4,64 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Assimp; using Assimp;
using OpenTK;
namespace Switch_Toolbox.Library namespace Switch_Toolbox.Library
{ {
public class AssimpHelper public class AssimpHelper
{ {
public static OpenTK.Matrix4 TKMatrix(Assimp.Matrix4x4 input)
{
return new OpenTK.Matrix4(input.A1, input.B1, input.C1, input.D1,
input.A2, input.B2, input.C2, input.D2,
input.A3, input.B3, input.C3, input.D3,
input.A4, input.B4, input.C4, input.D4);
}
public static OpenTK.Quaternion TKQuaternion(Assimp.Quaternion rot)
{
OpenTK.Quaternion quat = new OpenTK.Quaternion();
quat.X = rot.X;
quat.Y = rot.Y;
quat.Z = rot.Z;
quat.W = rot.W;
return quat;
}
public static Vector3 ToEulerAngles(Assimp.Quaternion q)
{
float PI = (float)Math.PI;
// Store the Euler angles in radians
Vector3 pitchYawRoll = new Vector3();
double sqw = q.W * q.W;
double sqx = q.X * q.X;
double sqy = q.Y * q.Y;
double sqz = q.Z * q.Z;
// If quaternion is normalised the unit is one, otherwise it is the correction factor
double unit = sqx + sqy + sqz + sqw;
double test = q.X * q.Y + q.Z * q.W;
if (test > 0.499f * unit)
{
// Singularity at north pole
pitchYawRoll.Y = 2f * (float)Math.Atan2(q.X, q.W); // Yaw
pitchYawRoll.X = PI * 0.5f; // Pitch
pitchYawRoll.Z = 0f; // Roll
return pitchYawRoll;
}
else if (test < -0.499f * unit)
{
// Singularity at south pole
pitchYawRoll.Y = -2f * (float)Math.Atan2(q.X, q.W); // Yaw
pitchYawRoll.X = -PI * 0.5f; // Pitch
pitchYawRoll.Z = 0f; // Roll
return pitchYawRoll;
}
pitchYawRoll.Y = (float)Math.Atan2(2 * q.Y * q.W - 2 * q.X * q.Z, sqx - sqy - sqz + sqw); // Yaw
pitchYawRoll.X = (float)Math.Asin(2 * test / unit); // Pitch
pitchYawRoll.Z = (float)Math.Atan2(2 * q.X * q.W - 2 * q.Y * q.Z, -sqx + sqy - sqz + sqw); // Roll
return pitchYawRoll;
}
} }
} }

View file

@ -10,11 +10,92 @@ using System.IO;
using System.Windows.Forms; using System.Windows.Forms;
using Switch_Toolbox.Library; using Switch_Toolbox.Library;
using Switch_Toolbox.Library.IO; using Switch_Toolbox.Library.IO;
using SFGraphics.GLObjects.Textures;
using OpenTK.Graphics.OpenGL;
namespace Switch_Toolbox.Library namespace Switch_Toolbox.Library
{ {
//Data from https://github.com/jam1garner/Smash-Forge/blob/master/Smash%20Forge/Filetypes/Textures/DDS.cs
public class DDS public class DDS
{ {
public enum CubemapFace
{
PosX,
NegX,
PosY,
NegY,
PosZ,
NegZ
}
[Flags]
public enum DDSD : uint
{
CAPS = 0x00000001,
HEIGHT = 0x00000002,
WIDTH = 0x00000004,
PITCH = 0x00000008,
PIXELFORMAT = 0x00001000,
MIPMAPCOUNT = 0x00020000,
LINEARSIZE = 0x00080000,
DEPTH = 0x00800000
}
[Flags]
public enum DDPF : uint
{
ALPHAPIXELS = 0x00000001,
ALPHA = 0x00000002,
FOURCC = 0x00000004,
RGB = 0x00000040,
YUV = 0x00000200,
LUMINANCE = 0x00020000,
}
[Flags]
public enum DDSCAPS : uint
{
COMPLEX = 0x00000008,
TEXTURE = 0x00001000,
MIPMAP = 0x00400000,
}
[Flags]
public enum DDSCAPS2 : uint
{
CUBEMAP = 0x00000200,
CUBEMAP_POSITIVEX = 0x00000400 | CUBEMAP,
CUBEMAP_NEGATIVEX = 0x00000800 | CUBEMAP,
CUBEMAP_POSITIVEY = 0x00001000 | CUBEMAP,
CUBEMAP_NEGATIVEY = 0x00002000 | CUBEMAP,
CUBEMAP_POSITIVEZ = 0x00004000 | CUBEMAP,
CUBEMAP_NEGATIVEZ = 0x00008000 | CUBEMAP,
CUBEMAP_ALLFACES = (CUBEMAP_POSITIVEX | CUBEMAP_NEGATIVEX |
CUBEMAP_POSITIVEY | CUBEMAP_NEGATIVEY |
CUBEMAP_POSITIVEZ | CUBEMAP_NEGATIVEZ),
VOLUME = 0x00200000
}
public static uint getFormatSize(uint fourCC)
{
switch (fourCC)
{
case 0x00000000: //RGBA
return 0x4;
case 0x31545844: //DXT1
return 0x8;
case 0x33545844: //DXT3
return 0x10;
case 0x35545844: //DXT5
return 0x10;
case 0x31495441: //ATI1
case 0x55344342: //BC4U
return 0x8;
case 0x32495441: //ATI2
case 0x55354342: //BC5U
return 0x10;
default:
return 0;
}
}
public Header header; public Header header;
public DX10Header DX10header; public DX10Header DX10header;
public class Header public class Header
@ -259,6 +340,26 @@ namespace Switch_Toolbox.Library
DX10header.arrayFlag = reader.ReadUInt32(); DX10header.arrayFlag = reader.ReadUInt32();
DX10header.miscFlags2 = reader.ReadUInt32(); DX10header.miscFlags2 = reader.ReadUInt32();
} }
public static TextureCubeMap CreateGLCubeMap(DDS dds)
{
TextureCubeMap texture = new TextureCubeMap();
List<byte[]> cubemap = GetArrayFaces(dds.bdata, 6);
texture.LoadImageData((int)dds.header.width,new SFGraphics.GLObjects.Textures.TextureFormats.TextureFormatUncompressed(PixelInternalFormat.Rgba,
OpenTK.Graphics.OpenGL.PixelFormat.Rgba, OpenTK.Graphics.OpenGL.PixelType.Float), cubemap[0],
cubemap[1], cubemap[2], cubemap[3], cubemap[4], cubemap[5]);
return texture;
}
public static List<byte[]> GetArrayFaces(byte[] data, uint Length)
{
using (FileReader reader = new FileReader(data))
{
List<byte[]> array = new List<byte[]>();
for (int i = 0; i < Length; i++)
array.Add(reader.ReadBytes(data.Length / (int)Length));
return array;
}
}
public void Save(DDS dds, string FileName, bool IsDX10 = false, List<List<byte[]>> data = null) public void Save(DDS dds, string FileName, bool IsDX10 = false, List<List<byte[]>> data = null)
{ {
FileWriter writer = new FileWriter(new FileStream(FileName, FileMode.Create, FileAccess.Write, FileShare.Write)); FileWriter writer = new FileWriter(new FileStream(FileName, FileMode.Create, FileAccess.Write, FileShare.Write));

View file

@ -2,6 +2,7 @@
using System.Diagnostics; using System.Diagnostics;
using System.Drawing; using System.Drawing;
using Switch_Toolbox.Library; using Switch_Toolbox.Library;
using System.Runtime.InteropServices;
namespace Switch_Toolbox.Library namespace Switch_Toolbox.Library
{ {
@ -180,8 +181,7 @@ namespace Switch_Toolbox.Library
return BitmapExtension.GetBitmap(Output, W * 4, H * 4); return BitmapExtension.GetBitmap(Output, W * 4, H * 4);
} }
public static Bitmap DecompressBC4(Byte[] data, int width, int height, bool IsSNORM)
public static Bitmap DecompressBC4(Byte[] data, int width, int height, bool IsSNORM)
{ {
int W = (width + 3) / 4; int W = (width + 3) / 4;
int H = (height + 3) / 4; int H = (height + 3) / 4;
@ -436,7 +436,50 @@ namespace Switch_Toolbox.Library
return BitmapExtension.GetBitmap(Output, W * 4, H * 4); return BitmapExtension.GetBitmap(Output, W * 4, H * 4);
} }
/* public static unsafe byte[] CreateImage(Byte[] data, int width, int height, DDS.DXGI_FORMAT format)
{
long inputRowPitch;
long inputSlicePitch;
TexHelper.Instance.ComputePitch((DXGI_FORMAT)format, width, height, out inputRowPitch, out inputSlicePitch, CP_FLAGS.NONE);
if (data.Length == inputSlicePitch)
{
byte* buf;
buf = (byte*)Marshal.AllocHGlobal((int)inputSlicePitch);
Marshal.Copy(data, 0, (IntPtr)buf, (int)inputSlicePitch);
DirectXTexNet.Image inputImage = new DirectXTexNet.Image(width, height, (DXGI_FORMAT)format, inputRowPitch, inputSlicePitch, (IntPtr)buf, null);
ScratchImage scratchImage = TexHelper.Instance.Initialize2D((DXGI_FORMAT)format, width, height, 1, 1, CP_FLAGS.NONE);
using (var comp = scratchImage.Compress(DXGI_FORMAT.BC1_UNORM, TEX_COMPRESS_FLAGS.PARALLEL, 0.5f))
{
long outRowPitch;
long outSlicePitch;
TexHelper.Instance.ComputePitch((DXGI_FORMAT)format, width, height, out outRowPitch, out outSlicePitch, CP_FLAGS.NONE);
byte[] result = new byte[outSlicePitch];
Marshal.Copy(result, 0, scratchImage.GetPixels(), (int)outSlicePitch);
return result;
}
}
return null;
}*/
public unsafe byte* PointerData(byte* data, int length)
{
byte[] safe = new byte[length];
for (int i = 0; i < length; i++)
safe[i] = data[i];
fixed (byte* converted = safe)
{
// This will update the safe and converted arrays.
for (int i = 0; i < length; i++)
converted[i]++;
return converted;
}
}
public static byte[] DecompressBlock(Byte[] data, int width, int height, DDS.DXGI_FORMAT format) public static byte[] DecompressBlock(Byte[] data, int width, int height, DDS.DXGI_FORMAT format)
{ {
return DirectXTex.ImageCompressor.Decompress(data, width, height, (int)format); return DirectXTex.ImageCompressor.Decompress(data, width, height, (int)format);
@ -447,10 +490,16 @@ namespace Switch_Toolbox.Library
} }
public static byte[] EncodePixelBlock(Byte[] data, int width, int height, DDS.DXGI_FORMAT format) public static byte[] EncodePixelBlock(Byte[] data, int width, int height, DDS.DXGI_FORMAT format)
{ {
if (format == DDS.DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM)
return data;
return DirectXTex.ImageConverter.Convert(data, width, height,(int)DDS.DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM, (int)format); return DirectXTex.ImageConverter.Convert(data, width, height,(int)DDS.DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM, (int)format);
} }
public static byte[] DecodePixelBlock(Byte[] data, int width, int height, DDS.DXGI_FORMAT format) public static byte[] DecodePixelBlock(Byte[] data, int width, int height, DDS.DXGI_FORMAT format)
{ {
if (format == DDS.DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM)
return data;
return DirectXTex.ImageConverter.Convert(data, width, height, (int)format, (int)DDS.DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM); return DirectXTex.ImageConverter.Convert(data, width, height, (int)format, (int)DDS.DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM);
} }

View file

@ -15,6 +15,22 @@ namespace Switch_Toolbox.Library
public BitmapExtension() public BitmapExtension()
{ {
}
public static List<byte[]> GenerateMipMaps(Bitmap bitmap)
{
List<byte[]> datas = new List<byte[]>();
datas.Add(ImageToByte(bitmap));
while (bitmap.Width / 2 > 0 && bitmap.Height / 2 > 0)
{
bitmap = Resize(bitmap, bitmap.Width / 2, bitmap.Height / 2);
datas.Add(ImageToByte(bitmap));
}
return datas;
}
public static Bitmap Resize(Image original, int width, int height)
{
return new Bitmap(original, new Size(width, height));
} }
public static Bitmap GetBitmap(byte[] Buffer, int Width, int Height, PixelFormat pixelFormat = PixelFormat.Format32bppArgb) public static Bitmap GetBitmap(byte[] Buffer, int Width, int Height, PixelFormat pixelFormat = PixelFormat.Format32bppArgb)
{ {
@ -143,9 +159,9 @@ namespace Switch_Toolbox.Library
for (int k = 0; k < resultBuffer.Length; k += 4) for (int k = 0; k < resultBuffer.Length; k += 4)
{ {
sourceBlue = resultBuffer[k]; sourceRed = resultBuffer[k];
sourceGreen = resultBuffer[k + 1]; sourceGreen = resultBuffer[k + 1];
sourceRed = resultBuffer[k + 2]; sourceBlue = resultBuffer[k + 2];
sourceAlpha = resultBuffer[k + 3]; sourceAlpha = resultBuffer[k + 3];
@ -245,9 +261,9 @@ namespace Switch_Toolbox.Library
break; break;
} }
resultBuffer[k] = resultBlue; resultBuffer[k] = resultRed;
resultBuffer[k + 1] = resultGreen; resultBuffer[k + 1] = resultGreen;
resultBuffer[k + 2] = resultRed; resultBuffer[k + 2] = resultBlue;
resultBuffer[k + 3] = resultAlpha; resultBuffer[k + 3] = resultAlpha;
} }

View file

@ -12,7 +12,8 @@ namespace Switch_Toolbox.Library
public abstract class TreeNodeCustom : TreeNode public abstract class TreeNodeCustom : TreeNode
{ {
public virtual void OnClick(TreeView treeview) { } public virtual void OnClick(TreeView treeview) { }
public virtual void OnMouseClick(TreeView treeview) { } public virtual void OnMouseLeftClick(TreeView treeview) { }
public virtual void OnMouseRightClick(TreeView treeview) { }
public virtual void OnDoubleMouseClick(TreeView treeview) { } public virtual void OnDoubleMouseClick(TreeView treeview) { }
public TreeNodeCustom() public TreeNodeCustom()

View file

@ -101,13 +101,13 @@
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(33)))), ((int)(((byte)(33)))), ((int)(((byte)(33))))); this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(33)))), ((int)(((byte)(33)))), ((int)(((byte)(33)))));
this.ClientSize = new System.Drawing.Size(602, 69);
this.Controls.Add(this.animationTrackBar); this.Controls.Add(this.animationTrackBar);
this.Controls.Add(this.totalFrame); this.Controls.Add(this.totalFrame);
this.Controls.Add(this.currentFrameUpDown); this.Controls.Add(this.currentFrameUpDown);
this.Controls.Add(this.animationPlayBtn); this.Controls.Add(this.animationPlayBtn);
this.Name = "AnimationPanel"; this.Name = "AnimationPanel";
this.Text = "AnimationPanel"; this.Size = new System.Drawing.Size(602, 69);
this.Load += new System.EventHandler(this.AnimationPanel_Load);
this.Click += new System.EventHandler(this.AnimationPanel_Click); this.Click += new System.EventHandler(this.AnimationPanel_Click);
this.Enter += new System.EventHandler(this.AnimationPanel_Enter); this.Enter += new System.EventHandler(this.AnimationPanel_Enter);
this.Leave += new System.EventHandler(this.AnimationPanel_Leave); this.Leave += new System.EventHandler(this.AnimationPanel_Leave);

View file

@ -25,10 +25,9 @@ namespace Switch_Toolbox.Library
public int AnimationSpeed = 60; public int AnimationSpeed = 60;
public float Frame = 0; public float Frame = 0;
public bool isPlaying; public bool isPlaying;
private bool isOpen = true; public bool isOpen = true;
private Thread renderThread; private Thread renderThread;
private GL_Core.GL_ControlModern gL_ControlModern1; public bool renderThreadIsUpdating = false;
private bool renderThreadIsUpdating = false;
private Animation currentAnimation; private Animation currentAnimation;
public Animation CurrentAnimation public Animation CurrentAnimation
@ -39,13 +38,16 @@ namespace Switch_Toolbox.Library
} }
set set
{ {
if (value == null)
return;
ResetModels(); ResetModels();
/* currentAnimation = value; currentAnimation = value;
totalFrame.Value = value.FrameCount; totalFrame.Value = value.FrameCount;
animationTrackBar.TickFrequency = 1; animationTrackBar.TickFrequency = 1;
animationTrackBar.SetRange(0, (int)value.FrameCount); animationTrackBar.SetRange(0, (int)value.FrameCount);
currentFrameUpDown.Value = 1; currentFrameUpDown.Value = 1;
currentFrameUpDown.Value = 0;*/ currentFrameUpDown.Value = 0;
} }
} }
@ -118,6 +120,9 @@ namespace Switch_Toolbox.Library
private void UpdateViewport() private void UpdateViewport()
{ {
if (IsDisposed)
return;
if (Viewport.Instance.gL_ControlModern1.InvokeRequired) if (Viewport.Instance.gL_ControlModern1.InvokeRequired)
{ {
Viewport.Instance.gL_ControlModern1.Invoke((MethodInvoker)delegate { Viewport.Instance.gL_ControlModern1.Invoke((MethodInvoker)delegate {
@ -226,7 +231,8 @@ namespace Switch_Toolbox.Library
SetAnimationsToFrame(currentFrame); SetAnimationsToFrame(currentFrame);
UpdateViewport(); if (!renderThreadIsUpdating || !isPlaying)
UpdateViewport();
} }
private void SetAnimationsToFrame(int frameNum) private void SetAnimationsToFrame(int frameNum)
{ {
@ -252,19 +258,19 @@ namespace Switch_Toolbox.Library
animationTrackBar.Value = (int)currentFrameUpDown.Value; animationTrackBar.Value = (int)currentFrameUpDown.Value;
} }
private void AnimationPanel_FormClosed(object sender, FormClosedEventArgs e) public void AnimationPanel_FormClosed()
{ {
isOpen = false; isOpen = false;
Dispose(); Dispose();
} }
private void AnimationPanel_Shown(object sender, EventArgs e) private void AnimationPanel_Load(object sender, EventArgs e)
{ {
// if (Viewport.Instance.gL_ControlModern1 != null) if (Viewport.Instance.gL_ControlModern1 != null)
// Viewport.Instance.gL_ControlModern1.VSync = Runtime.enableVSync; Viewport.Instance.gL_ControlModern1.VSync = Runtime.enableVSync;
// renderThread = new Thread(new ThreadStart(RenderAndAnimationLoop)); renderThread = new Thread(new ThreadStart(RenderAndAnimationLoop));
// renderThread.Start(); renderThread.Start();
} }
private void AnimationPanel_Enter(object sender, EventArgs e) private void AnimationPanel_Enter(object sender, EventArgs e)
@ -281,5 +287,12 @@ namespace Switch_Toolbox.Library
{ {
renderThreadIsUpdating = false; renderThreadIsUpdating = false;
} }
public void ClosePanel()
{
renderThreadIsUpdating = false;
isOpen = false;
Dispose();
renderThread.Abort();
}
} }
} }

View file

@ -0,0 +1,236 @@
namespace Switch_Toolbox.Library.GUI
{
partial class CubeMapFaceCreator
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(CubeMapFaceCreator));
this.pictureBoxCustom6 = new Switch_Toolbox.Library.Forms.PictureBoxCustom();
this.pictureBoxCustom1 = new Switch_Toolbox.Library.Forms.PictureBoxCustom();
this.pictureBoxCustom2 = new Switch_Toolbox.Library.Forms.PictureBoxCustom();
this.pictureBoxCustom3 = new Switch_Toolbox.Library.Forms.PictureBoxCustom();
this.pictureBoxCustom4 = new Switch_Toolbox.Library.Forms.PictureBoxCustom();
this.pictureBoxCustom5 = new Switch_Toolbox.Library.Forms.PictureBoxCustom();
this.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.label4 = new System.Windows.Forms.Label();
this.label5 = new System.Windows.Forms.Label();
this.label6 = new System.Windows.Forms.Label();
((System.ComponentModel.ISupportInitialize)(this.pictureBoxCustom6)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBoxCustom1)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBoxCustom2)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBoxCustom3)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBoxCustom4)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBoxCustom5)).BeginInit();
this.SuspendLayout();
//
// pictureBoxCustom6
//
this.pictureBoxCustom6.BackColor = System.Drawing.Color.Transparent;
this.pictureBoxCustom6.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("pictureBoxCustom6.BackgroundImage")));
this.pictureBoxCustom6.Location = new System.Drawing.Point(217, 12);
this.pictureBoxCustom6.Name = "pictureBoxCustom6";
this.pictureBoxCustom6.Size = new System.Drawing.Size(200, 200);
this.pictureBoxCustom6.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
this.pictureBoxCustom6.TabIndex = 5;
this.pictureBoxCustom6.TabStop = false;
//
// pictureBoxCustom1
//
this.pictureBoxCustom1.BackColor = System.Drawing.Color.Transparent;
this.pictureBoxCustom1.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("pictureBoxCustom1.BackgroundImage")));
this.pictureBoxCustom1.Location = new System.Drawing.Point(217, 218);
this.pictureBoxCustom1.Name = "pictureBoxCustom1";
this.pictureBoxCustom1.Size = new System.Drawing.Size(200, 200);
this.pictureBoxCustom1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
this.pictureBoxCustom1.TabIndex = 6;
this.pictureBoxCustom1.TabStop = false;
//
// pictureBoxCustom2
//
this.pictureBoxCustom2.BackColor = System.Drawing.Color.Transparent;
this.pictureBoxCustom2.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("pictureBoxCustom2.BackgroundImage")));
this.pictureBoxCustom2.Location = new System.Drawing.Point(11, 218);
this.pictureBoxCustom2.Name = "pictureBoxCustom2";
this.pictureBoxCustom2.Size = new System.Drawing.Size(200, 200);
this.pictureBoxCustom2.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
this.pictureBoxCustom2.TabIndex = 7;
this.pictureBoxCustom2.TabStop = false;
//
// pictureBoxCustom3
//
this.pictureBoxCustom3.BackColor = System.Drawing.Color.Transparent;
this.pictureBoxCustom3.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("pictureBoxCustom3.BackgroundImage")));
this.pictureBoxCustom3.Location = new System.Drawing.Point(217, 424);
this.pictureBoxCustom3.Name = "pictureBoxCustom3";
this.pictureBoxCustom3.Size = new System.Drawing.Size(200, 200);
this.pictureBoxCustom3.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
this.pictureBoxCustom3.TabIndex = 8;
this.pictureBoxCustom3.TabStop = false;
//
// pictureBoxCustom4
//
this.pictureBoxCustom4.BackColor = System.Drawing.Color.Transparent;
this.pictureBoxCustom4.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("pictureBoxCustom4.BackgroundImage")));
this.pictureBoxCustom4.Location = new System.Drawing.Point(423, 218);
this.pictureBoxCustom4.Name = "pictureBoxCustom4";
this.pictureBoxCustom4.Size = new System.Drawing.Size(200, 200);
this.pictureBoxCustom4.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
this.pictureBoxCustom4.TabIndex = 9;
this.pictureBoxCustom4.TabStop = false;
//
// pictureBoxCustom5
//
this.pictureBoxCustom5.BackColor = System.Drawing.Color.Transparent;
this.pictureBoxCustom5.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("pictureBoxCustom5.BackgroundImage")));
this.pictureBoxCustom5.Location = new System.Drawing.Point(629, 218);
this.pictureBoxCustom5.Name = "pictureBoxCustom5";
this.pictureBoxCustom5.Size = new System.Drawing.Size(200, 200);
this.pictureBoxCustom5.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
this.pictureBoxCustom5.TabIndex = 10;
this.pictureBoxCustom5.TabStop = false;
//
// label1
//
this.label1.AutoSize = true;
this.label1.BackColor = System.Drawing.Color.White;
this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label1.ForeColor = System.Drawing.Color.Black;
this.label1.Location = new System.Drawing.Point(274, 300);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(76, 24);
this.label1.TabIndex = 11;
this.label1.Text = "FRONT";
//
// label2
//
this.label2.AutoSize = true;
this.label2.BackColor = System.Drawing.Color.White;
this.label2.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label2.ForeColor = System.Drawing.Color.Black;
this.label2.Location = new System.Drawing.Point(488, 300);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(67, 24);
this.label2.TabIndex = 12;
this.label2.Text = "RIGHT";
//
// label3
//
this.label3.AutoSize = true;
this.label3.BackColor = System.Drawing.Color.White;
this.label3.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label3.ForeColor = System.Drawing.Color.Black;
this.label3.Location = new System.Drawing.Point(78, 300);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(57, 24);
this.label3.TabIndex = 13;
this.label3.Text = "LEFT";
//
// label4
//
this.label4.AutoSize = true;
this.label4.BackColor = System.Drawing.Color.White;
this.label4.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label4.ForeColor = System.Drawing.Color.Black;
this.label4.Location = new System.Drawing.Point(716, 300);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(60, 24);
this.label4.TabIndex = 14;
this.label4.Text = "BACK";
//
// label5
//
this.label5.AutoSize = true;
this.label5.BackColor = System.Drawing.Color.White;
this.label5.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label5.ForeColor = System.Drawing.Color.Black;
this.label5.Location = new System.Drawing.Point(283, 90);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(49, 24);
this.label5.TabIndex = 15;
this.label5.Text = "TOP";
//
// label6
//
this.label6.AutoSize = true;
this.label6.BackColor = System.Drawing.Color.White;
this.label6.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label6.ForeColor = System.Drawing.Color.Black;
this.label6.Location = new System.Drawing.Point(268, 528);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(92, 24);
this.label6.TabIndex = 16;
this.label6.Text = "BOTTOM";
//
// CubeMapFaceCreator
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(40)))), ((int)(((byte)(40)))), ((int)(((byte)(40)))));
this.ClientSize = new System.Drawing.Size(840, 630);
this.Controls.Add(this.label6);
this.Controls.Add(this.label5);
this.Controls.Add(this.label4);
this.Controls.Add(this.label3);
this.Controls.Add(this.label2);
this.Controls.Add(this.label1);
this.Controls.Add(this.pictureBoxCustom5);
this.Controls.Add(this.pictureBoxCustom4);
this.Controls.Add(this.pictureBoxCustom3);
this.Controls.Add(this.pictureBoxCustom2);
this.Controls.Add(this.pictureBoxCustom1);
this.Controls.Add(this.pictureBoxCustom6);
this.Name = "CubeMapFaceCreator";
this.Text = "CubeMap Face Creator";
((System.ComponentModel.ISupportInitialize)(this.pictureBoxCustom6)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBoxCustom1)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBoxCustom2)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBoxCustom3)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBoxCustom4)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBoxCustom5)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private Forms.PictureBoxCustom pictureBoxCustom6;
private Forms.PictureBoxCustom pictureBoxCustom1;
private Forms.PictureBoxCustom pictureBoxCustom2;
private Forms.PictureBoxCustom pictureBoxCustom3;
private Forms.PictureBoxCustom pictureBoxCustom4;
private Forms.PictureBoxCustom pictureBoxCustom5;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.Label label6;
}
}

View file

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Switch_Toolbox.Library.GUI
{
public partial class CubeMapFaceCreator : Form
{
public CubeMapFaceCreator()
{
InitializeComponent();
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -131,8 +131,8 @@
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(40)))), ((int)(((byte)(40)))), ((int)(((byte)(40))))); this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(40)))), ((int)(((byte)(40)))), ((int)(((byte)(40)))));
this.ClientSize = new System.Drawing.Size(358, 450); this.ClientSize = new System.Drawing.Size(358, 450);
this.Controls.Add(this.panel1);
this.Controls.Add(this.treeView1); this.Controls.Add(this.treeView1);
this.Controls.Add(this.panel1);
this.Name = "ObjectList"; this.Name = "ObjectList";
this.Text = "ObjectList"; this.Text = "ObjectList";
this.DockStateChanged += new System.EventHandler(this.ObjectList_DockStateChanged); this.DockStateChanged += new System.EventHandler(this.ObjectList_DockStateChanged);

View file

@ -74,32 +74,13 @@ namespace Switch_Toolbox.Library
} }
} }
AnimationPanel AnimationPanel = LoadAnimationPanel(); if (Viewport.Instance.animationPanel1 != null)
if (AnimationPanel != null)
{ {
AnimationPanel.CurrentAnimation = running; Console.WriteLine("running" + running.Text);
Viewport.Instance.animationPanel1.CurrentAnimation = running;
} }
} }
} }
public AnimationPanel LoadAnimationPanel()
{
Form form1 = Application.OpenForms[0];
foreach (Control control in form1.Controls)
{
if (control is DockPanel)
{
foreach (DockContent ctrl in ((DockPanel)control).Contents)
{
if (ctrl is AnimationPanel)
{
// return (AnimationPanel)ctrl;
}
}
}
}
return null;
}
private void ApplyThumbnailSetting(Runtime.ThumbnailSize size) private void ApplyThumbnailSetting(Runtime.ThumbnailSize size)
{ {
@ -211,14 +192,15 @@ namespace Switch_Toolbox.Library
private void treeView1_MouseClick(object sender, MouseEventArgs e) private void treeView1_MouseClick(object sender, MouseEventArgs e)
{ {
if (e.Button == MouseButtons.Left) TreeViewHitTestInfo info = treeView1.HitTest(treeView1.PointToClient(Cursor.Position));
if (info != null && info.Node is TreeNodeCustom)
{ {
TreeViewHitTestInfo info = treeView1.HitTest(treeView1.PointToClient(Cursor.Position)); if (e.Button == MouseButtons.Left)
if (info != null && info.Node is TreeNodeCustom) ((TreeNodeCustom)info.Node).OnMouseLeftClick(treeView1);
{ else if (e.Button == MouseButtons.Right)
((TreeNodeCustom)info.Node).OnMouseClick(treeView1); ((TreeNodeCustom)info.Node).OnMouseRightClick(treeView1);
treeView1.SelectedNode = info.Node;
} treeView1.SelectedNode = info.Node;
} }
} }
} }

View file

@ -32,10 +32,10 @@
this.animationPanel1 = new Switch_Toolbox.Library.AnimationPanel(); this.animationPanel1 = new Switch_Toolbox.Library.AnimationPanel();
this.contextMenuStripDark1 = new Switch_Toolbox.Library.Forms.ContextMenuStripDark(); this.contextMenuStripDark1 = new Switch_Toolbox.Library.Forms.ContextMenuStripDark();
this.shadingToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.shadingToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.normalsShadingToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.translateToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.translateToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.rotateToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.rotateToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.scaleToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.scaleToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.normalsShadingToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.contextMenuStripDark1.SuspendLayout(); this.contextMenuStripDark1.SuspendLayout();
this.SuspendLayout(); this.SuspendLayout();
// //
@ -85,7 +85,6 @@
// //
// shadingToolStripMenuItem // shadingToolStripMenuItem
// //
this.shadingToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {});
this.shadingToolStripMenuItem.Image = global::Switch_Toolbox.Library.Properties.Resources.diffuseSphere; this.shadingToolStripMenuItem.Image = global::Switch_Toolbox.Library.Properties.Resources.diffuseSphere;
this.shadingToolStripMenuItem.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None; this.shadingToolStripMenuItem.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None;
this.shadingToolStripMenuItem.Name = "shadingToolStripMenuItem"; this.shadingToolStripMenuItem.Name = "shadingToolStripMenuItem";
@ -95,16 +94,6 @@
this.shadingToolStripMenuItem.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageAboveText; this.shadingToolStripMenuItem.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageAboveText;
this.shadingToolStripMenuItem.DropDownItemClicked += new System.Windows.Forms.ToolStripItemClickedEventHandler(this.shadingToolStripMenuItem_DropDownItemClicked); this.shadingToolStripMenuItem.DropDownItemClicked += new System.Windows.Forms.ToolStripItemClickedEventHandler(this.shadingToolStripMenuItem_DropDownItemClicked);
// //
// normalsShadingToolStripMenuItem
//
this.normalsShadingToolStripMenuItem.ForeColor = System.Drawing.Color.White;
this.normalsShadingToolStripMenuItem.Image = global::Switch_Toolbox.Library.Properties.Resources.normalsSphere;
this.normalsShadingToolStripMenuItem.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None;
this.normalsShadingToolStripMenuItem.Name = "normalsShadingToolStripMenuItem";
this.normalsShadingToolStripMenuItem.Size = new System.Drawing.Size(204, 46);
this.normalsShadingToolStripMenuItem.Text = "Normals Shading";
this.normalsShadingToolStripMenuItem.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageAboveText;
//
// translateToolStripMenuItem // translateToolStripMenuItem
// //
this.translateToolStripMenuItem.Image = global::Switch_Toolbox.Library.Properties.Resources.translateGizmo; this.translateToolStripMenuItem.Image = global::Switch_Toolbox.Library.Properties.Resources.translateGizmo;
@ -132,6 +121,16 @@
this.scaleToolStripMenuItem.Text = "Scale"; this.scaleToolStripMenuItem.Text = "Scale";
this.scaleToolStripMenuItem.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageAboveText; this.scaleToolStripMenuItem.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageAboveText;
// //
// normalsShadingToolStripMenuItem
//
this.normalsShadingToolStripMenuItem.ForeColor = System.Drawing.Color.White;
this.normalsShadingToolStripMenuItem.Image = global::Switch_Toolbox.Library.Properties.Resources.normalsSphere;
this.normalsShadingToolStripMenuItem.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None;
this.normalsShadingToolStripMenuItem.Name = "normalsShadingToolStripMenuItem";
this.normalsShadingToolStripMenuItem.Size = new System.Drawing.Size(204, 46);
this.normalsShadingToolStripMenuItem.Text = "Normals Shading";
this.normalsShadingToolStripMenuItem.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageAboveText;
//
// Viewport // Viewport
// //
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@ -150,6 +149,7 @@
this.Name = "Viewport"; this.Name = "Viewport";
this.ShowHint = WeifenLuo.WinFormsUI.Docking.DockState.Unknown; this.ShowHint = WeifenLuo.WinFormsUI.Docking.DockState.Unknown;
this.Text = "Viewport"; this.Text = "Viewport";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Viewport_FormClosing);
this.contextMenuStripDark1.ResumeLayout(false); this.contextMenuStripDark1.ResumeLayout(false);
this.contextMenuStripDark1.PerformLayout(); this.contextMenuStripDark1.PerformLayout();
this.ResumeLayout(false); this.ResumeLayout(false);
@ -160,7 +160,7 @@
#endregion #endregion
public GL_Core.GL_ControlModern gL_ControlModern1; public GL_Core.GL_ControlModern gL_ControlModern1;
private AnimationPanel animationPanel1; public AnimationPanel animationPanel1;
private Forms.ContextMenuStripDark contextMenuStripDark1; private Forms.ContextMenuStripDark contextMenuStripDark1;
private System.Windows.Forms.ToolStripMenuItem shadingToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem shadingToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem translateToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem translateToolStripMenuItem;

View file

@ -121,5 +121,10 @@ namespace Switch_Toolbox.Library
i++; i++;
} }
} }
private void Viewport_FormClosing(object sender, FormClosingEventArgs e)
{
animationPanel1.ClosePanel();
}
} }
} }

View file

@ -158,6 +158,22 @@ namespace Switch_Toolbox.Library.IO
{ {
Write(Encoding.ASCII.GetBytes(value)); Write(Encoding.ASCII.GetBytes(value));
} }
public void WriteUint64Offset(long target)
{
long pos = Position;
using (TemporarySeek(target, SeekOrigin.Begin))
{
Write(pos);
}
}
public void WriteUint32Offset(long target)
{
long pos = Position;
using (TemporarySeek(target, SeekOrigin.Begin))
{
Write((uint)pos);
}
}
} }
public class FileExt public class FileExt
{ {

View file

@ -8,6 +8,7 @@ using SFGraphics.GLObjects.Textures.TextureFormats;
using OpenTK; using OpenTK;
using OpenTK.Graphics.OpenGL; using OpenTK.Graphics.OpenGL;
using Smash_Forge.Rendering; using Smash_Forge.Rendering;
using Switch_Toolbox.Library.IO;
namespace Switch_Toolbox.Library namespace Switch_Toolbox.Library
{ {
@ -25,15 +26,20 @@ namespace Switch_Toolbox.Library
uvTestPattern = new Texture2D(); uvTestPattern = new Texture2D();
uvTestPattern.LoadImageData(Properties.Resources.UVPattern); uvTestPattern.LoadImageData(Properties.Resources.UVPattern);
// DDS specularSdr = new DDS(Properties.Resources.specularSDR); if (Runtime.EnablePBR)
// specularPbr = NUT.CreateTextureCubeMap(specularSdr.ToNutTexture()); {
byte[] decompSpecular = STLibraryCompression.GZIP.Decompress(Properties.Resources.specularSDR);
DDS specularSdr = new DDS(decompSpecular);
// specularPbr = DDS.CreateGLCubeMap(specularSdr);
}
// DDS diffuseSdr = new DDS(Properties.Resources.diffuseSDR);
// diffusePbr = CreateTextureCubeMap(bntx.textureData.texture); // DDS diffuseSdr = new DDS(Properties.Resources.diffuseSDR);
// diffusePbr = CreateTextureCubeMap(bntx.textureData.texture);
// Don't use mipmaps. // Don't use mipmaps.
// diffusePbr.MinFilter = TextureMinFilter.Linear; // diffusePbr.MinFilter = TextureMinFilter.Linear;
// diffusePbr.MagFilter = TextureMagFilter.Linear; // diffusePbr.MagFilter = TextureMagFilter.Linear;
} }
public static void DrawSkyBox(Matrix4 RotationMatrix) public static void DrawSkyBox(Matrix4 RotationMatrix)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 945 KiB

View file

@ -25,6 +25,7 @@ namespace Switch_Toolbox.Library
public static ViewportShading viewportShading; public static ViewportShading viewportShading;
public static bool IsDebugMode = false; //Enables experimental features and other things to debug. public static bool IsDebugMode = false; //Enables experimental features and other things to debug.
public static bool DisableViewport = false; public static bool DisableViewport = false;
public static bool EnablePBR = false;
public static bool enableVSync = false; public static bool enableVSync = false;
public static float floorSize = 30f; public static float floorSize = 30f;

View file

@ -54,8 +54,8 @@
<Reference Include="K4os.Hash.xxHash, Version=1.0.5.0, Culture=neutral, PublicKeyToken=32cd54395057cec3, processorArchitecture=MSIL"> <Reference Include="K4os.Hash.xxHash, Version=1.0.5.0, Culture=neutral, PublicKeyToken=32cd54395057cec3, processorArchitecture=MSIL">
<HintPath>..\Switch_Toolbox\Lib\K4os.Hash.xxHash.dll</HintPath> <HintPath>..\Switch_Toolbox\Lib\K4os.Hash.xxHash.dll</HintPath>
</Reference> </Reference>
<Reference Include="LZ4"> <Reference Include="LZ4, Version=1.0.15.93, Culture=neutral, PublicKeyToken=62e1b5ec1eec9bdd, processorArchitecture=MSIL">
<HintPath>..\Switch_Toolbox\Lib\LZ4.dll</HintPath> <HintPath>..\packages\lz4net.1.0.15.93\lib\net4-client\LZ4.dll</HintPath>
</Reference> </Reference>
<Reference Include="Microsoft.VisualBasic" /> <Reference Include="Microsoft.VisualBasic" />
<Reference Include="OpenTK"> <Reference Include="OpenTK">
@ -129,6 +129,12 @@
<Compile Include="GUI\Assimp Settings.Designer.cs"> <Compile Include="GUI\Assimp Settings.Designer.cs">
<DependentUpon>Assimp Settings.cs</DependentUpon> <DependentUpon>Assimp Settings.cs</DependentUpon>
</Compile> </Compile>
<Compile Include="GUI\CubeMapFaceCreator.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="GUI\CubeMapFaceCreator.Designer.cs">
<DependentUpon>CubeMapFaceCreator.cs</DependentUpon>
</Compile>
<Compile Include="GUI\Viewport.cs"> <Compile Include="GUI\Viewport.cs">
<SubType>Form</SubType> <SubType>Form</SubType>
</Compile> </Compile>
@ -223,6 +229,9 @@
<EmbeddedResource Include="GUI\AssimpMeshSelector.resx"> <EmbeddedResource Include="GUI\AssimpMeshSelector.resx">
<DependentUpon>AssimpMeshSelector.cs</DependentUpon> <DependentUpon>AssimpMeshSelector.cs</DependentUpon>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Include="GUI\CubeMapFaceCreator.resx">
<DependentUpon>CubeMapFaceCreator.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="GUI\ObjectList.resx"> <EmbeddedResource Include="GUI\ObjectList.resx">
<DependentUpon>ObjectList.cs</DependentUpon> <DependentUpon>ObjectList.cs</DependentUpon>
</EmbeddedResource> </EmbeddedResource>

View file

@ -33,6 +33,17 @@ namespace Switch_Toolbox.Library
{ {
return new Vector4(v.X, v.Y, v.Z, v.W); return new Vector4(v.X, v.Y, v.Z, v.W);
} }
public static byte[] CombineByteArray(params byte[][] arrays)
{
byte[] rv = new byte[arrays.Sum(a => a.Length)];
int offset = 0;
foreach (byte[] array in arrays)
{
System.Buffer.BlockCopy(array, 0, rv, offset, array.Length);
offset += array.Length;
}
return rv;
}
static int i = 0; static int i = 0;
public static string RenameDuplicateString(List<string> strings, string oldString) public static string RenameDuplicateString(List<string> strings, string oldString)
{ {

View file

@ -11,3 +11,10 @@ C:\Users\Nathan\Documents\GitHub\Switch_Toolbox\Switch-Toolbox\Updater\bin\Relea
C:\Users\Nathan\Documents\GitHub\Switch_Toolbox\Switch-Toolbox\Updater\obj\Release\Updater.csproj.CoreCompileInputs.cache C:\Users\Nathan\Documents\GitHub\Switch_Toolbox\Switch-Toolbox\Updater\obj\Release\Updater.csproj.CoreCompileInputs.cache
C:\Users\Nathan\Documents\GitHub\Switch_Toolbox\Switch-Toolbox\Updater\obj\Release\Updater.exe C:\Users\Nathan\Documents\GitHub\Switch_Toolbox\Switch-Toolbox\Updater\obj\Release\Updater.exe
C:\Users\Nathan\Documents\GitHub\Switch_Toolbox\Switch-Toolbox\Updater\obj\Release\Updater.pdb C:\Users\Nathan\Documents\GitHub\Switch_Toolbox\Switch-Toolbox\Updater\obj\Release\Updater.pdb
C:\Users\Nathan\Documents\GitHub\Switch_Toolbox\Switch-Toolbox - Copy\Updater\bin\Release\Updater.exe.config
C:\Users\Nathan\Documents\GitHub\Switch_Toolbox\Switch-Toolbox - Copy\Updater\bin\Release\Updater.exe
C:\Users\Nathan\Documents\GitHub\Switch_Toolbox\Switch-Toolbox - Copy\Updater\bin\Release\Updater.pdb
C:\Users\Nathan\Documents\GitHub\Switch_Toolbox\Switch-Toolbox - Copy\Updater\obj\Release\Updater.csprojAssemblyReference.cache
C:\Users\Nathan\Documents\GitHub\Switch_Toolbox\Switch-Toolbox - Copy\Updater\obj\Release\Updater.csproj.CoreCompileInputs.cache
C:\Users\Nathan\Documents\GitHub\Switch_Toolbox\Switch-Toolbox - Copy\Updater\obj\Release\Updater.exe
C:\Users\Nathan\Documents\GitHub\Switch_Toolbox\Switch-Toolbox - Copy\Updater\obj\Release\Updater.pdb

Binary file not shown.

Binary file not shown.