-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Optimized how Dead Space models are loaded, since some were really sl…
…ow to load.
- Loading branch information
1 parent
7f81995
commit 6d5ff77
Showing
36 changed files
with
358 additions
and
131 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
50 changes: 50 additions & 0 deletions
50
FinModelUtility/Fin/Fin/src/image/io/image/Dxt1ImageReader.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
using System; | ||
|
||
using fin.image.io.tile; | ||
|
||
using schema.binary; | ||
|
||
using SixLabors.ImageSharp.PixelFormats; | ||
|
||
namespace fin.image.io.image { | ||
public class Dxt1ImageReader( | ||
int width, | ||
int height, | ||
int subTileCountInAxis = 2, | ||
int subTileSizeInAxis = 4, | ||
bool flipBlocksHorizontally = true) | ||
: IImageReader<IImage<Rgb24>> { | ||
private readonly Dxt1TileReader tileReader_ | ||
= new(subTileCountInAxis, subTileSizeInAxis, flipBlocksHorizontally); | ||
|
||
public IImage<Rgb24> ReadImage(IBinaryReader br) { | ||
Span<ushort> shortBuffer = stackalloc ushort[2]; | ||
Span<Rgb24> paletteBuffer = stackalloc Rgb24[4]; | ||
Span<byte> indicesBuffer = stackalloc byte[4]; | ||
|
||
var image = this.tileReader_.CreateImage(width, height); | ||
using var imageLock = image.Lock(); | ||
var scan0 = imageLock.Pixels; | ||
|
||
var tileXCount | ||
= (int) Math.Ceiling(1f * width / this.tileReader_.TileWidth); | ||
var tileYCount = height / this.tileReader_.TileHeight; | ||
|
||
for (var tileY = 0; tileY < tileYCount; ++tileY) { | ||
for (var tileX = 0; tileX < tileXCount; ++tileX) { | ||
this.tileReader_.Decode(br, | ||
scan0, | ||
tileX, | ||
tileY, | ||
width, | ||
height, | ||
shortBuffer, | ||
paletteBuffer, | ||
indicesBuffer); | ||
} | ||
} | ||
|
||
return image; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
142 changes: 142 additions & 0 deletions
142
FinModelUtility/Fin/Fin/src/image/io/tile/Dxt1TileReader.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
using System; | ||
using System.Runtime.CompilerServices; | ||
|
||
using fin.image.formats; | ||
using fin.util.color; | ||
|
||
using schema.binary; | ||
|
||
using SixLabors.ImageSharp.PixelFormats; | ||
|
||
namespace fin.image.io.tile { | ||
public readonly struct Dxt1TileReader( | ||
int subTileCountInAxis = 2, | ||
int subTileSizeInAxis = 4, | ||
bool flipBlocksHorizontally = true) | ||
: ITileReader<Rgb24> { | ||
public IImage<Rgb24> CreateImage(int width, int height) | ||
=> new Rgb24Image(PixelFormat.DXT1, width, height); | ||
|
||
private readonly int tileSizeInAxis_ | ||
= subTileCountInAxis * subTileSizeInAxis; | ||
|
||
public int TileWidth => this.tileSizeInAxis_; | ||
public int TileHeight => this.tileSizeInAxis_; | ||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public unsafe void Decode(IBinaryReader br, | ||
Span<Rgb24> scan0, | ||
int tileX, | ||
int tileY, | ||
int imageWidth, | ||
int imageHeight) { | ||
Span<ushort> shortBuffer = stackalloc ushort[2]; | ||
Span<Rgb24> paletteBuffer = stackalloc Rgb24[4]; | ||
Span<byte> indicesBuffer = stackalloc byte[4]; | ||
this.Decode(br, | ||
scan0, | ||
tileX, | ||
tileY, | ||
imageWidth, | ||
imageHeight, | ||
shortBuffer, | ||
paletteBuffer, | ||
indicesBuffer); | ||
} | ||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public void Decode(IBinaryReader br, | ||
Span<Rgb24> scan0, | ||
int tileX, | ||
int tileY, | ||
int imageWidth, | ||
int imageHeight, | ||
Span<ushort> shortBuffer, | ||
Span<Rgb24> paletteBuffer, | ||
Span<byte> indicesBuffer) { | ||
for (var j = 0; j < subTileCountInAxis; ++j) { | ||
for (var i = 0; i < subTileCountInAxis; ++i) { | ||
DecodeSubblock_( | ||
br, | ||
shortBuffer, | ||
scan0, | ||
paletteBuffer, | ||
indicesBuffer, | ||
tileX * TileWidth + i * subTileSizeInAxis, | ||
tileY * TileHeight + j * subTileSizeInAxis, | ||
imageWidth, | ||
imageHeight); | ||
} | ||
} | ||
} | ||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
private void DecodeSubblock_( | ||
IBinaryReader br, | ||
Span<ushort> shortBuffer, | ||
Span<Rgb24> scan0, | ||
Span<Rgb24> paletteBuffer, | ||
Span<byte> indicesBuffer, | ||
int imageX, | ||
int imageY, | ||
int imageWidth, | ||
int imageHeight) { | ||
br.ReadUInt16s(shortBuffer); | ||
DecodePalette_(shortBuffer, paletteBuffer); | ||
|
||
br.ReadBytes(indicesBuffer); | ||
for (var j = 0; j < subTileSizeInAxis; ++j) { | ||
if (imageY + j >= imageHeight) { | ||
break; | ||
} | ||
|
||
var indices = indicesBuffer[j]; | ||
var scan0Offset = (imageY + j) * imageWidth + imageX; | ||
|
||
for (var i = 0; i < subTileSizeInAxis; ++i) { | ||
if (imageX + i >= imageWidth) { | ||
break; | ||
} | ||
|
||
var shiftIndexAmount = !flipBlocksHorizontally ? i : 3 - i; | ||
var index = (indices >> (2 * shiftIndexAmount)) & 0b11; | ||
scan0[scan0Offset + i] = paletteBuffer[index]; | ||
} | ||
} | ||
} | ||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
private static void DecodePalette_( | ||
ReadOnlySpan<ushort> colorValues, | ||
Span<Rgb24> palette) { | ||
var color1Value = colorValues[0]; | ||
var color2Value = colorValues[1]; | ||
|
||
ColorUtil.SplitRgb565(color1Value, out var r1, out var g1, out var b1); | ||
ColorUtil.SplitRgb565(color2Value, out var r2, out var g2, out var b2); | ||
|
||
palette[0] = new Rgb24(r1, g1, b1); | ||
palette[1] = new Rgb24(r2, g2, b2); | ||
|
||
if (color1Value > color2Value) { | ||
// 3rd color in palette is 1/3 from 1st to 2nd. | ||
palette[2] = new Rgb24( | ||
(byte) (((r1 << 1) + r2) / 3), | ||
(byte) (((g1 << 1) + g2) / 3), | ||
(byte) (((b1 << 1) + b2) / 3)); | ||
// 4th color in palette is 2/3 from 1st to 2nd. | ||
palette[3] = new Rgb24( | ||
(byte) ((r1 + (r2 << 1)) / 3), | ||
(byte) ((g1 + (g2 << 1)) / 3), | ||
(byte) ((b1 + (b2 << 1)) / 3)); | ||
} else { | ||
// 3rd color in palette is halfway between 1st and 2nd. | ||
palette[2] = new Rgb24((byte) ((r1 + r2) >> 1), | ||
(byte) ((g1 + g2) >> 1), | ||
(byte) ((b1 + b2) >> 1)); | ||
// 4th color in palette is black. | ||
palette[3] = new Rgb24(0, 0, 0); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.