diff options
| -rw-r--r-- | Scripts/DataDecoder.asset | 10 | ||||
| -rw-r--r-- | Scripts/DataDecoder.cs | 67 |
2 files changed, 64 insertions, 13 deletions
diff --git a/Scripts/DataDecoder.asset b/Scripts/DataDecoder.asset index ddfcdfe..26b5e70 100644 --- a/Scripts/DataDecoder.asset +++ b/Scripts/DataDecoder.asset @@ -104,13 +104,13 @@ MonoBehaviour: Data: - Name: $k Entry: 1 - Data: tileSize + Data: tileToCheck - Name: $v Entry: 7 Data: 5|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: <Name>k__BackingField Entry: 1 - Data: tileSize + Data: tileToCheck - Name: <UserType>k__BackingField Entry: 7 Data: 6|System.RuntimeType, mscorlib @@ -158,13 +158,13 @@ MonoBehaviour: Data: - Name: $k Entry: 1 - Data: tileToCheck + Data: tileSize - Name: $v Entry: 7 Data: 8|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: <Name>k__BackingField Entry: 1 - Data: tileToCheck + Data: tileSize - Name: <UserType>k__BackingField Entry: 9 Data: 6 @@ -182,7 +182,7 @@ MonoBehaviour: Data: - Name: <IsSerialized>k__BackingField Entry: 5 - Data: true + Data: false - Name: _fieldAttributes Entry: 7 Data: 9|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib diff --git a/Scripts/DataDecoder.cs b/Scripts/DataDecoder.cs index 810c46a..1128e2f 100644 --- a/Scripts/DataDecoder.cs +++ b/Scripts/DataDecoder.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using UdonSharp; using UnityEngine; using VRC.SDK3.Rendering; @@ -6,9 +7,12 @@ using VRC.Udon.Common.Interfaces; public class DataDecoder : UdonSharpBehaviour { public RenderTexture sourceTexture; - public int tileSize = 8; public int tileToCheck = 0; + private int tileSize = 8; + // Minimum size (in pixels) of a tile. This is shared with our tixl operator. + private const int kMinTileSize = 4; + private const int kMaxTileSize = 128; private Color32[] pixelData; private bool hasData = false; private int readWidth; @@ -18,9 +22,8 @@ public class DataDecoder : UdonSharpBehaviour void Update() { - if (sourceTexture == null || tileSize <= 0) return; + if (sourceTexture == null) return; - // TODO get more than one column int requestWidth = Mathf.Min(tileSize, sourceTexture.width); int requestHeight = sourceTexture.height; int pixelCount = requestWidth * requestHeight; @@ -62,21 +65,69 @@ public class DataDecoder : UdonSharpBehaviour private void ProcessTiles() { - if (pixelData == null || readWidth <= 0 || readHeight <= 0) return; + // Get the tile size. + { + int oldTileSize = tileSize; + tileSize = kMinTileSize; + tileSize = Parse24BitTile(0); + tileSize = Mathf.Clamp(tileSize, kMinTileSize, kMaxTileSize); + if (tileSize != oldTileSize) { + Debug.Log($"Tile size changed from {oldTileSize} to {tileSize}"); + } + } + + // Get the length. This is in units of subpixels. So we will need to access + // ceil(length/3) tiles. + int lengthSubpixels = Parse24BitTile(1); + int lengthTiles = (int) Mathf.Ceil(lengthSubpixels/3.0f); + + // Collect all nibbles into a flat array. Note that these are still + // encoded. + var nibbles = new List<int>(lengthSubpixels); + for (int tile_i = 0; tile_i < lengthTiles; tile_i++) { + GetTileRGB(tile_i+2, out int r, out int g, out int b); + nibbles.Add(r); + if (nibbles.Count < nibbles.Capacity) { + nibbles.Add(g); + } + if (nibbles.Count < nibbles.Capacity) { + nibbles.Add(b); + } + } + + // Convert nibbles to bytes. + var bytes = nibbles; + for (int i = 0; i < nibbles.Count/2; i++) { + // See DataEncoder.cs. It puts the upper 4 bits before the lower 4 bits. + bytes[i] = (nibbles[2*i] & 0xF0) | ((nibbles[2*i+1] & 0xF0) >> 4); + } + // Remove second half of list. + bytes.RemoveRange(nibbles.Count/2, nibbles.Count/2); int tilesPerColumn = (int) Mathf.Floor(readHeight / tileSize); + } + + private int Parse24BitTile(int tileIdx) + { + GetTileRGB(tileIdx, out int r, out int g, out int b); + int data = 0; + data |= DecodeNibble(r); + data |= DecodeNibble(g) << 4; + data |= DecodeNibble(b) << 8; + return data; + } - GetTileRGB(tileToCheck, out int r, out int g, out int b); - Debug.Log($"Tile {tileToCheck}: R={r}, G={g}, B={b}"); + private int DecodeNibble(int subpixel) { + return (subpixel >> 4) & 0x0F; } - private void GetTileRGB(int tileIndex, out int r, out int g, out int b) + private void GetTileRGB(int tileIdx, out int r, out int g, out int b) { r = 0; g = 0; b = 0; - int tileY = tileIndex * tileSize; + int tileY = tileIdx * tileSize; int centerY = tileY + tileSize / 2; if (centerY >= readHeight) return; |
