mirror of
https://github.com/openharmony/third_party_meshoptimizer.git
synced 2026-07-19 12:03:07 -04:00
Merge pull request #692 from zeux/gltf-bas
gltfpack: Implement support for KHR_texture_basisu inputs
This commit is contained in:
@@ -81,6 +81,7 @@ gltfpack supports most Khronos extensions and some multi-vendor extensions in th
|
||||
- KHR_materials_variants
|
||||
- KHR_materials_volume
|
||||
- KHR_mesh_quantization
|
||||
- KHR_texture_basisu
|
||||
- KHR_texture_transform
|
||||
- EXT_meshopt_compression
|
||||
|
||||
|
||||
+3
-1
@@ -98,11 +98,13 @@ static const char* prepareEncode(basisu::basis_compressor_params& params, const
|
||||
{
|
||||
std::string img_data;
|
||||
std::string mime_type;
|
||||
std::string result;
|
||||
|
||||
if (!readImage(image, input_path, img_data, mime_type))
|
||||
return "error reading source file";
|
||||
|
||||
if (mime_type != "image/png" && mime_type != "image/jpeg")
|
||||
return NULL;
|
||||
|
||||
int width = 0, height = 0;
|
||||
if (!getDimensions(img_data, mime_type.c_str(), width, height))
|
||||
return "error parsing image header";
|
||||
|
||||
+3
-1
@@ -452,6 +452,7 @@ static void process(cgltf_data* data, const char* input_path, const char* output
|
||||
bool ext_unlit = false;
|
||||
bool ext_instancing = false;
|
||||
bool ext_texture_transform = false;
|
||||
bool ext_texture_basisu = false;
|
||||
|
||||
size_t accr_offset = 0;
|
||||
size_t node_offset = 0;
|
||||
@@ -509,6 +510,7 @@ static void process(cgltf_data* data, const char* input_path, const char* output
|
||||
|
||||
assert(textures[i].remap == int(texture_offset));
|
||||
texture_offset++;
|
||||
ext_texture_basisu = ext_texture_basisu || texture.has_basisu;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < data->materials_count; ++i)
|
||||
@@ -834,7 +836,7 @@ static void process(cgltf_data* data, const char* input_path, const char* output
|
||||
{"KHR_materials_unlit", ext_unlit, false},
|
||||
{"KHR_materials_variants", data->variants_count > 0, false},
|
||||
{"KHR_lights_punctual", data->lights_count > 0, false},
|
||||
{"KHR_texture_basisu", !json_textures.empty() && settings.texture_ktx2, true},
|
||||
{"KHR_texture_basisu", (!json_textures.empty() && settings.texture_ktx2) || ext_texture_basisu, true},
|
||||
{"EXT_mesh_gpu_instancing", ext_instancing, true},
|
||||
};
|
||||
|
||||
|
||||
+55
-8
@@ -107,12 +107,12 @@ bool readImage(const cgltf_image& image, const char* input_path, std::string& da
|
||||
}
|
||||
}
|
||||
|
||||
static int readInt16(const std::string& data, size_t offset)
|
||||
static int readInt16BE(const std::string& data, size_t offset)
|
||||
{
|
||||
return (unsigned char)data[offset] * 256 + (unsigned char)data[offset + 1];
|
||||
}
|
||||
|
||||
static int readInt32(const std::string& data, size_t offset)
|
||||
static int readInt32BE(const std::string& data, size_t offset)
|
||||
{
|
||||
return (unsigned((unsigned char)data[offset]) << 24) |
|
||||
(unsigned((unsigned char)data[offset + 1]) << 16) |
|
||||
@@ -120,6 +120,14 @@ static int readInt32(const std::string& data, size_t offset)
|
||||
unsigned((unsigned char)data[offset + 3]);
|
||||
}
|
||||
|
||||
static int readInt32LE(const std::string& data, size_t offset)
|
||||
{
|
||||
return unsigned((unsigned char)data[offset]) |
|
||||
(unsigned((unsigned char)data[offset + 1]) << 8) |
|
||||
(unsigned((unsigned char)data[offset + 2]) << 16) |
|
||||
(unsigned((unsigned char)data[offset + 3]) << 24);
|
||||
}
|
||||
|
||||
static bool getDimensionsPng(const std::string& data, int& width, int& height)
|
||||
{
|
||||
if (data.size() < 8 + 8 + 13 + 4)
|
||||
@@ -132,8 +140,8 @@ static bool getDimensionsPng(const std::string& data, int& width, int& height)
|
||||
if (data.compare(12, 4, "IHDR") != 0)
|
||||
return false;
|
||||
|
||||
width = readInt32(data, 16);
|
||||
height = readInt32(data, 20);
|
||||
width = readInt32BE(data, 16);
|
||||
height = readInt32BE(data, 20);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -169,13 +177,13 @@ static bool getDimensionsJpeg(const std::string& data, int& width, int& height)
|
||||
if (offset + 10 > data.size())
|
||||
return false;
|
||||
|
||||
width = readInt16(data, offset + 7);
|
||||
height = readInt16(data, offset + 5);
|
||||
width = readInt16BE(data, offset + 7);
|
||||
height = readInt16BE(data, offset + 5);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
offset += 2 + readInt16(data, offset + 2);
|
||||
offset += 2 + readInt16BE(data, offset + 2);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -202,7 +210,7 @@ static bool hasTransparencyPng(const std::string& data)
|
||||
|
||||
while (offset + 12 <= data.size())
|
||||
{
|
||||
int length = readInt32(data, offset);
|
||||
int length = readInt32BE(data, offset);
|
||||
|
||||
if (length < 0)
|
||||
return false;
|
||||
@@ -216,10 +224,49 @@ static bool hasTransparencyPng(const std::string& data)
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool hasTransparencyKtx2(const std::string& data)
|
||||
{
|
||||
if (data.size() < 12 + 17 * 4)
|
||||
return false;
|
||||
|
||||
const char* signature = "\xabKTX 20\xbb\r\n\x1a\n";
|
||||
if (data.compare(0, 12, signature) != 0)
|
||||
return false;
|
||||
|
||||
int dfdOffset = readInt32LE(data, 48);
|
||||
int dfdLength = readInt32LE(data, 52);
|
||||
|
||||
if (dfdLength < 4 + 24 + 16 || unsigned(dfdOffset) > data.size() || unsigned(dfdLength) > data.size() - dfdOffset)
|
||||
return false;
|
||||
|
||||
const int KDF_DF_MODEL_ETC1S = 163;
|
||||
const int KDF_DF_MODEL_UASTC = 166;
|
||||
const int KHR_DF_CHANNEL_UASTC_RGBA = 3;
|
||||
const int KHR_DF_CHANNEL_ETC1S_RGB = 0;
|
||||
const int KHR_DF_CHANNEL_ETC1S_AAA = 15;
|
||||
|
||||
int colorModel = readInt32LE(data, dfdOffset + 12) & 0xff;
|
||||
int channelType1 = (readInt32LE(data, dfdOffset + 28) >> 24) & 0xf;
|
||||
int channelType2 = dfdLength >= 4 + 24 + 16 * 2 ? (readInt32LE(data, dfdOffset + 44) >> 24) & 0xf : channelType1;
|
||||
|
||||
if (colorModel == KDF_DF_MODEL_ETC1S)
|
||||
{
|
||||
return channelType1 == KHR_DF_CHANNEL_ETC1S_RGB && channelType2 == KHR_DF_CHANNEL_ETC1S_AAA;
|
||||
}
|
||||
else if (colorModel == KDF_DF_MODEL_UASTC)
|
||||
{
|
||||
return channelType1 == KHR_DF_CHANNEL_UASTC_RGBA;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool hasAlpha(const std::string& data, const char* mime_type)
|
||||
{
|
||||
if (strcmp(mime_type, "image/png") == 0)
|
||||
return hasTransparencyPng(data);
|
||||
else if (strcmp(mime_type, "image/ktx2") == 0)
|
||||
return hasTransparencyKtx2(data);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
+22
-3
@@ -11,6 +11,12 @@ static bool areTexturesEqual(const cgltf_texture& lhs, const cgltf_texture& rhs)
|
||||
if (lhs.sampler != rhs.sampler)
|
||||
return false;
|
||||
|
||||
if (lhs.has_basisu != rhs.has_basisu)
|
||||
return false;
|
||||
|
||||
if (lhs.basisu_image != rhs.basisu_image)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -435,6 +441,17 @@ bool hasValidTransform(const cgltf_texture_view& view)
|
||||
return false;
|
||||
}
|
||||
|
||||
static const cgltf_image* getTextureImage(const cgltf_texture* texture)
|
||||
{
|
||||
if (texture && texture->image)
|
||||
return texture->image;
|
||||
|
||||
if (texture && texture->has_basisu && texture->basisu_image)
|
||||
return texture->basisu_image;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void analyzeMaterialTexture(const cgltf_texture_view& view, TextureKind kind, MaterialInfo& mi, cgltf_data* data, std::vector<TextureInfo>& textures, std::vector<ImageInfo>& images)
|
||||
{
|
||||
mi.usesTextureTransform |= hasValidTransform(view);
|
||||
@@ -442,9 +459,9 @@ static void analyzeMaterialTexture(const cgltf_texture_view& view, TextureKind k
|
||||
if (view.texture)
|
||||
textures[view.texture - data->textures].keep = true;
|
||||
|
||||
if (view.texture && view.texture->image)
|
||||
if (const cgltf_image* image = getTextureImage(view.texture))
|
||||
{
|
||||
ImageInfo& info = images[view.texture->image - data->images];
|
||||
ImageInfo& info = images[image - data->images];
|
||||
|
||||
mi.textureSetMask |= 1u << view.texcoord;
|
||||
mi.needsTangents |= (kind == TextureKind_Normal);
|
||||
@@ -549,7 +566,9 @@ static bool shouldKeepAlpha(const cgltf_texture_view& color, float alpha, cgltf_
|
||||
if (alpha != 1.f)
|
||||
return true;
|
||||
|
||||
return color.texture && color.texture->image && getChannels(*color.texture->image, images[color.texture->image - data->images], input_path) == 4;
|
||||
const cgltf_image* image = getTextureImage(color.texture);
|
||||
|
||||
return image && getChannels(*image, images[image - data->images], input_path) == 4;
|
||||
}
|
||||
|
||||
void optimizeMaterials(cgltf_data* data, const char* input_path, std::vector<ImageInfo>& images)
|
||||
|
||||
@@ -530,8 +530,6 @@ static cgltf_data* parseGltf(cgltf_data* data, cgltf_result result, std::vector<
|
||||
*error = getError(result, data);
|
||||
else if (requiresExtension(data, "KHR_draco_mesh_compression"))
|
||||
*error = "file requires Draco mesh compression support";
|
||||
else if (requiresExtension(data, "KHR_texture_basisu"))
|
||||
*error = "file requires BasisU texture support";
|
||||
else if (requiresExtension(data, "EXT_mesh_gpu_instancing"))
|
||||
*error = "file requires mesh instancing support";
|
||||
else if (needsDummyBuffers(data))
|
||||
|
||||
+18
-7
@@ -952,27 +952,38 @@ void writeImage(std::string& json, std::vector<BufferView>& views, const cgltf_i
|
||||
|
||||
void writeTexture(std::string& json, const cgltf_texture& texture, const ImageInfo* info, cgltf_data* data, const Settings& settings)
|
||||
{
|
||||
if (texture.sampler)
|
||||
{
|
||||
append(json, "\"sampler\":");
|
||||
append(json, size_t(texture.sampler - data->samplers));
|
||||
}
|
||||
|
||||
if (texture.image)
|
||||
{
|
||||
if (texture.sampler)
|
||||
{
|
||||
append(json, "\"sampler\":");
|
||||
append(json, size_t(texture.sampler - data->samplers));
|
||||
append(json, ",");
|
||||
}
|
||||
|
||||
if (info && settings.texture_mode[info->kind] != TextureMode_Raw)
|
||||
{
|
||||
comma(json);
|
||||
append(json, "\"extensions\":{\"KHR_texture_basisu\":{\"source\":");
|
||||
append(json, size_t(texture.image - data->images));
|
||||
append(json, "}}");
|
||||
|
||||
return; // skip input basisu image if present, as we replace it with the one we encoded
|
||||
}
|
||||
else
|
||||
{
|
||||
comma(json);
|
||||
append(json, "\"source\":");
|
||||
append(json, size_t(texture.image - data->images));
|
||||
}
|
||||
}
|
||||
|
||||
if (texture.has_basisu && texture.basisu_image)
|
||||
{
|
||||
comma(json);
|
||||
append(json, "\"extensions\":{\"KHR_texture_basisu\":{\"source\":");
|
||||
append(json, size_t(texture.basisu_image - data->images));
|
||||
append(json, "}}");
|
||||
}
|
||||
}
|
||||
|
||||
void writeMeshAttributes(std::string& json, std::vector<BufferView>& views, std::string& json_accessors, size_t& accr_offset, const Mesh& mesh, int target, const QuantizationPosition& qp, const QuantizationTexture& qt, const Settings& settings)
|
||||
|
||||
Reference in New Issue
Block a user