Image の MimeType を ITextureDeserializer に伝達する

This commit is contained in:
Masataka SUMI
2021-12-08 19:01:22 +09:00
parent e597913806
commit c96d4c1331
12 changed files with 130 additions and 61 deletions

View File

@@ -314,18 +314,18 @@ namespace UniGLTF
return result;
}
public ArraySegment<byte> GetBytesFromImage(int imageIndex)
public (ArraySegment<byte> binary, string mimeType)? GetBytesFromImage(int imageIndex)
{
if (imageIndex < 0 || imageIndex >= GLTF.images.Count) return new ArraySegment<byte>();
if (imageIndex < 0 || imageIndex >= GLTF.images.Count) return default;
var image = GLTF.images[imageIndex];
if (string.IsNullOrEmpty(image.uri))
{
return GetBytesFromBufferView(image.bufferView);
return (GetBytesFromBufferView(image.bufferView), image.mimeType);
}
else
{
return GetBytesFromUri(image.uri);
return (GetBytesFromUri(image.uri), image.mimeType);
}
}
}

View File

@@ -44,7 +44,7 @@ namespace UniGLTF
{
var (offset, scale) =
GltfTextureImporter.GetTextureOffsetAndScale(src.pbrMetallicRoughness.baseColorTexture);
var (key, textureParam) = GltfTextureImporter.CreateSRGB(data,
var (key, textureParam) = GltfTextureImporter.CreateSrgb(data,
src.pbrMetallicRoughness.baseColorTexture.index, offset, scale);
textureSlots.Add("_MainTex", textureParam);
}

View File

@@ -54,7 +54,7 @@ namespace UniGLTF
public static (SubAssetKey, TextureDescriptor) BaseColorTexture(GltfData data, glTFMaterial src)
{
var (offset, scale) = GltfTextureImporter.GetTextureOffsetAndScale(src.pbrMetallicRoughness.baseColorTexture);
return GltfTextureImporter.CreateSRGB(data, src.pbrMetallicRoughness.baseColorTexture.index, offset, scale);
return GltfTextureImporter.CreateSrgb(data, src.pbrMetallicRoughness.baseColorTexture.index, offset, scale);
}
public static (SubAssetKey, TextureDescriptor) StandardTexture(GltfData data, glTFMaterial src)
@@ -84,7 +84,7 @@ namespace UniGLTF
public static (SubAssetKey, TextureDescriptor) EmissiveTexture(GltfData data, glTFMaterial src)
{
var (offset, scale) = GltfTextureImporter.GetTextureOffsetAndScale(src.emissiveTexture);
return GltfTextureImporter.CreateSRGB(data, src.emissiveTexture.index, offset, scale);
return GltfTextureImporter.CreateSrgb(data, src.emissiveTexture.index, offset, scale);
}
}

View File

@@ -11,32 +11,48 @@ namespace UniGLTF
/// </summary>
public static class GltfTextureImporter
{
public static Byte[] ToArray(ArraySegment<byte> bytes)
/// <summary>
/// glTF の Texture が存在せず Image のみのものを、Texture として扱いたい場合の関数.
/// </summary>
public static (SubAssetKey, TextureDescriptor) CreateSrgbFromOnlyImage(GltfData data, int imageIndex, string uniqueName, string uri)
{
if (bytes.Array == null)
{
return new byte[] { };
}
else if (bytes.Offset == 0 && bytes.Count == bytes.Array.Length)
{
return bytes.Array;
}
else
{
Byte[] result = new byte[bytes.Count];
Buffer.BlockCopy(bytes.Array, bytes.Offset, result, 0, result.Length);
return result;
}
var name = TextureImportName.GetUnityObjectName(TextureImportTypes.sRGB, uniqueName, uri);
var texDesc = new TextureDescriptor(
uniqueName,
string.Empty,
uri,
Vector2.zero,
Vector2.one,
default,
TextureImportTypes.sRGB,
default,
default,
() =>
{
var imageBytes = data.GetBytesFromImage(imageIndex);
return Task.FromResult<(byte[], string)?>((ToArray(imageBytes?.binary ?? default), null));
},
default, default, default, default, default);
return (texDesc.SubAssetKey, texDesc);
}
public static (SubAssetKey, TextureDescriptor) CreateSRGB(GltfData data, int textureIndex, Vector2 offset, Vector2 scale)
public static (SubAssetKey, TextureDescriptor) CreateSrgb(GltfData data, int textureIndex, Vector2 offset, Vector2 scale)
{
var gltfTexture = data.GLTF.textures[textureIndex];
var gltfImage = data.GLTF.images[gltfTexture.source];
var name = TextureImportName.GetUnityObjectName(TextureImportTypes.sRGB, gltfTexture.name, gltfImage.uri);
var sampler = TextureSamplerUtil.CreateSampler(data.GLTF, textureIndex);
GetTextureBytesAsync getTextureBytesAsync = () => Task.FromResult(ToArray(GetImageBytesFromTextureIndex(data, textureIndex)));
var param = new TextureDescriptor(name, gltfImage.GetExt(), gltfImage.uri, offset, scale, sampler, TextureImportTypes.sRGB, default, default, getTextureBytesAsync, default, default, default, default, default);
var param = new TextureDescriptor(
name,
gltfImage.GetExt(),
gltfImage.uri,
offset, scale,
sampler,
TextureImportTypes.sRGB,
default,
default,
() => Task.FromResult(GetImageBytesFromTextureIndex(data, textureIndex)),
default, default, default, default, default);
return (param.SubAssetKey, param);
}
@@ -46,8 +62,18 @@ namespace UniGLTF
var gltfImage = data.GLTF.images[gltfTexture.source];
var name = TextureImportName.GetUnityObjectName(TextureImportTypes.Linear, gltfTexture.name, gltfImage.uri);
var sampler = TextureSamplerUtil.CreateSampler(data.GLTF, textureIndex);
GetTextureBytesAsync getTextureBytesAsync = () => Task.FromResult(ToArray(GetImageBytesFromTextureIndex(data, textureIndex)));
var param = new TextureDescriptor(name, gltfImage.GetExt(), gltfImage.uri, offset, scale, sampler, TextureImportTypes.Linear, default, default, getTextureBytesAsync, default, default, default, default, default);
var param = new TextureDescriptor(
name,
gltfImage.GetExt(),
gltfImage.uri,
offset,
scale,
sampler,
TextureImportTypes.Linear,
default,
default,
() => Task.FromResult(GetImageBytesFromTextureIndex(data, textureIndex)),
default, default, default, default, default);
return (param.SubAssetKey, param);
}
@@ -57,8 +83,18 @@ namespace UniGLTF
var gltfImage = data.GLTF.images[gltfTexture.source];
var name = TextureImportName.GetUnityObjectName(TextureImportTypes.NormalMap, gltfTexture.name, gltfImage.uri);
var sampler = TextureSamplerUtil.CreateSampler(data.GLTF, textureIndex);
GetTextureBytesAsync getTextureBytesAsync = () => Task.FromResult(ToArray(GetImageBytesFromTextureIndex(data, textureIndex)));
var param = new TextureDescriptor(name, gltfImage.GetExt(), gltfImage.uri, offset, scale, sampler, TextureImportTypes.NormalMap, default, default, getTextureBytesAsync, default, default, default, default, default);
var param = new TextureDescriptor(
name,
gltfImage.GetExt(),
gltfImage.uri,
offset,
scale,
sampler,
TextureImportTypes.NormalMap,
default,
default,
() => Task.FromResult(GetImageBytesFromTextureIndex(data, textureIndex)),
default, default, default, default, default);
return (param.SubAssetKey, param);
}
@@ -73,7 +109,7 @@ namespace UniGLTF
var gltfTexture = data.GLTF.textures[metallicRoughnessTextureIndex.Value];
name = TextureImportName.GetUnityObjectName(TextureImportTypes.StandardMap, gltfTexture.name, data.GLTF.images[gltfTexture.source].uri);
sampler = TextureSamplerUtil.CreateSampler(data.GLTF, metallicRoughnessTextureIndex.Value);
getMetallicRoughnessAsync = () => Task.FromResult(ToArray(GetImageBytesFromTextureIndex(data, metallicRoughnessTextureIndex.Value)));
getMetallicRoughnessAsync = () => Task.FromResult(GetImageBytesFromTextureIndex(data, metallicRoughnessTextureIndex.Value));
}
GetTextureBytesAsync getOcclusionAsync = default;
@@ -85,10 +121,22 @@ namespace UniGLTF
name = TextureImportName.GetUnityObjectName(TextureImportTypes.StandardMap, gltfTexture.name, data.GLTF.images[gltfTexture.source].uri);
}
sampler = TextureSamplerUtil.CreateSampler(data.GLTF, occlusionTextureIndex.Value);
getOcclusionAsync = () => Task.FromResult(ToArray(GetImageBytesFromTextureIndex(data, occlusionTextureIndex.Value)));
getOcclusionAsync = () => Task.FromResult(GetImageBytesFromTextureIndex(data, occlusionTextureIndex.Value));
}
var texDesc = new TextureDescriptor(name, ".png", null, offset, scale, sampler, TextureImportTypes.StandardMap, metallicFactor, roughnessFactor, getMetallicRoughnessAsync, getOcclusionAsync, default, default, default, default);
var texDesc = new TextureDescriptor(
name,
".png",
null,
offset,
scale,
sampler,
TextureImportTypes.StandardMap,
metallicFactor,
roughnessFactor,
getMetallicRoughnessAsync,
getOcclusionAsync,
default, default, default, default);
return (texDesc.SubAssetKey, texDesc);
}
@@ -124,7 +172,7 @@ namespace UniGLTF
return (offset, scale);
}
public static ArraySegment<byte> GetImageBytesFromTextureIndex(GltfData data, int textureIndex)
public static (byte[] binary, string mimeType)? GetImageBytesFromTextureIndex(GltfData data, int textureIndex)
{
if (Application.isPlaying)
{
@@ -140,20 +188,45 @@ namespace UniGLTF
}
}
return data.GetBytesFromImage(imageIndex);
if (!imageIndex.HasValue) return default;
var imageBytes = data.GetBytesFromImage(imageIndex.Value);
return (ToArray(imageBytes?.binary ?? default), imageBytes?.mimeType);
}
else
{
// NOTE: Editor の場合は通常通り読み込む.
return data.GetBytesFromImage(GetImageIndexFromTexture(data, textureIndex));
var imageIndex = GetImageIndexFromTexture(data, textureIndex);
if (!imageIndex.HasValue) return default;
var imageBytes = data.GetBytesFromImage(imageIndex.Value);
return (ToArray(imageBytes?.binary ?? default), imageBytes?.mimeType);
}
}
private static int GetImageIndexFromTexture(GltfData data, int textureIndex)
private static int? GetImageIndexFromTexture(GltfData data, int textureIndex)
{
if (textureIndex < 0 || textureIndex >= data.GLTF.textures.Count) return -1;
if (textureIndex < 0 || textureIndex >= data.GLTF.textures.Count) return default;
return data.GLTF.textures[textureIndex].source;
}
private static byte[] ToArray(ArraySegment<byte> bytes)
{
if (bytes.Array == null)
{
return new byte[] { };
}
else if (bytes.Offset == 0 && bytes.Count == bytes.Array.Length)
{
return bytes.Array;
}
else
{
var result = new byte[bytes.Count];
Buffer.BlockCopy(bytes.Array, bytes.Offset, result, 0, result.Length);
return result;
}
}
}
}

View File

@@ -292,7 +292,7 @@ namespace VRM
meta.Title = gltfMeta.title;
if (gltfMeta.texture >= 0)
{
var (key, param) = GltfTextureImporter.CreateSRGB(Data, gltfMeta.texture, Vector2.zero, Vector2.one);
var (key, param) = GltfTextureImporter.CreateSrgb(Data, gltfMeta.texture, Vector2.zero, Vector2.one);
meta.Thumbnail = await TextureFactory.GetTextureAsync(param, awaitCaller) as Texture2D;
}
meta.AllowedUser = gltfMeta.allowedUser;

View File

@@ -36,7 +36,7 @@ namespace VRM
texture = GltfTextureImporter.CreateNormal(data, textureIdx, offset, scale);
break;
default:
texture = GltfTextureImporter.CreateSRGB(data, textureIdx, offset, scale);
texture = GltfTextureImporter.CreateSrgb(data, textureIdx, offset, scale);
break;
}
return true;

View File

@@ -69,7 +69,7 @@ namespace VRM
{
if (vrm.meta.texture > -1)
{
texture = GltfTextureImporter.CreateSRGB(data, vrm.meta.texture, Vector2.zero, Vector2.one);
texture = GltfTextureImporter.CreateSrgb(data, vrm.meta.texture, Vector2.zero, Vector2.one);
return true;
}

View File

@@ -151,7 +151,7 @@ namespace UniVRM10
try
{
var (offset, scale) = GetTextureOffsetAndScale(info);
pair = GltfTextureImporter.CreateSRGB(data, info.index, offset, scale);
pair = GltfTextureImporter.CreateSrgb(data, info.index, offset, scale);
return true;
}
catch (NullReferenceException)

View File

@@ -106,18 +106,7 @@ namespace UniVRM10
}
var uniqueName = GlbLowLevelParser.FixNameUnique(used, imageName);
var objectName = TextureImportName.GetUnityObjectName(TextureImportTypes.sRGB, uniqueName, gltfImage.uri);
GetTextureBytesAsync getThumbnailImageBytesAsync = () =>
{
var bytes = data.GetBytesFromImage(imageIndex);
return Task.FromResult(GltfTextureImporter.ToArray(bytes));
};
var texDesc = new TextureDescriptor(objectName, gltfImage.GetExt(), gltfImage.uri, Vector2.zero, Vector2.one, default, TextureImportTypes.sRGB, default, default,
getThumbnailImageBytesAsync, default, default,
default, default, default
);
value = (texDesc.SubAssetKey, texDesc);
value = GltfTextureImporter.CreateSrgbFromOnlyImage(data, imageIndex, uniqueName, gltfImage.uri);
return true;
}
}

View File

@@ -12,6 +12,11 @@ namespace VRMShaders
/// </summary>
public byte[] ImageData { get; }
/// <summary>
/// Texture の mimeType
/// </summary>
public string DataMimeType { get; }
/// <summary>
/// Texture に求められる色空間
/// </summary>
@@ -37,9 +42,10 @@ namespace VRMShaders
/// </summary>
public TextureWrapMode WrapModeV { get; }
internal DeserializingTextureInfo(byte[] imageData, ColorSpace colorSpace, bool useMipmap, FilterMode filterMode, TextureWrapMode wrapModeU, TextureWrapMode wrapModeV)
internal DeserializingTextureInfo(byte[] imageData, string dataMimeType, ColorSpace colorSpace, bool useMipmap, FilterMode filterMode, TextureWrapMode wrapModeU, TextureWrapMode wrapModeV)
{
ImageData = imageData;
DataMimeType = dataMimeType;
ColorSpace = colorSpace;
UseMipmap = useMipmap;
FilterMode = filterMode;
@@ -47,9 +53,10 @@ namespace VRMShaders
WrapModeV = wrapModeV;
}
internal DeserializingTextureInfo(byte[] imageData, ColorSpace colorSpace, SamplerParam samplerParam)
internal DeserializingTextureInfo(byte[] imageData, string dataMimeType, ColorSpace colorSpace, SamplerParam samplerParam)
{
ImageData = imageData;
DataMimeType = dataMimeType;
ColorSpace = colorSpace;
UseMipmap = samplerParam.EnableMipMap;
FilterMode = samplerParam.FilterMode;

View File

@@ -13,7 +13,7 @@ namespace VRMShaders
/// File.WriteAllBytes
/// </summary>
/// <returns></returns>
public delegate Task<byte[]> GetTextureBytesAsync();
public delegate Task<(byte[] binary, string mimeType)?> GetTextureBytesAsync();
/// <summary>
/// 入力 glTF ファイルを Import した結果生成される、UnityEngine.Texture のアセット 1 つを確定させる Import 情報。

View File

@@ -80,7 +80,7 @@ namespace VRMShaders
// https://docs.unity3d.com/2018.4/Documentation/Manual/StandardShaderMaterialParameterNormalMap.html
var data0 = await texDesc.Index0();
var rawTexture = await TextureDeserializer.LoadTextureAsync(
new DeserializingTextureInfo(data0, ColorSpace.Linear, texDesc.Sampler),
new DeserializingTextureInfo(data0?.binary, data0?.mimeType, ColorSpace.Linear, texDesc.Sampler),
awaitCaller);
rawTexture.name = subAssetKey.Name;
_textureCache.Add(subAssetKey, rawTexture);
@@ -96,14 +96,14 @@ namespace VRMShaders
{
var data0 = await texDesc.Index0();
metallicRoughnessTexture = await TextureDeserializer.LoadTextureAsync(
new DeserializingTextureInfo(data0, ColorSpace.Linear, texDesc.Sampler),
new DeserializingTextureInfo(data0?.binary, data0?.mimeType, ColorSpace.Linear, texDesc.Sampler),
awaitCaller);
}
if (texDesc.Index1 != null)
{
var data1 = await texDesc.Index1();
occlusionTexture = await TextureDeserializer.LoadTextureAsync(
new DeserializingTextureInfo(data1, ColorSpace.Linear, texDesc.Sampler),
new DeserializingTextureInfo(data1?.binary, data1?.mimeType, ColorSpace.Linear, texDesc.Sampler),
awaitCaller);
}
@@ -123,7 +123,7 @@ namespace VRMShaders
{
var data0 = await texDesc.Index0();
var rawTexture = await TextureDeserializer.LoadTextureAsync(
new DeserializingTextureInfo(data0, ColorSpace.sRGB, texDesc.Sampler),
new DeserializingTextureInfo(data0?.binary, data0?.mimeType, ColorSpace.sRGB, texDesc.Sampler),
awaitCaller);
rawTexture.name = subAssetKey.Name;
_textureCache.Add(subAssetKey, rawTexture);
@@ -133,7 +133,7 @@ namespace VRMShaders
{
var data0 = await texDesc.Index0();
var rawTexture = await TextureDeserializer.LoadTextureAsync(
new DeserializingTextureInfo(data0, ColorSpace.Linear, texDesc.Sampler),
new DeserializingTextureInfo(data0?.binary, data0?.mimeType, ColorSpace.Linear, texDesc.Sampler),
awaitCaller);
rawTexture.name = subAssetKey.Name;
_textureCache.Add(subAssetKey, rawTexture);