Skip to content

Commit f6fd69d

Browse files
authored
Merge pull request #966 from zeux/gltf-khr
gltfpack: Introduce support for KHR_meshopt_compression
2 parents 19bb5e6 + 646b7dc commit f6fd69d

5 files changed

Lines changed: 36 additions & 28 deletions

File tree

‎extern/cgltf.h‎

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,7 @@ typedef enum cgltf_meshopt_compression_filter {
296296
cgltf_meshopt_compression_filter_octahedral,
297297
cgltf_meshopt_compression_filter_quaternion,
298298
cgltf_meshopt_compression_filter_exponential,
299+
cgltf_meshopt_compression_filter_color,
299300
cgltf_meshopt_compression_filter_max_enum
300301
} cgltf_meshopt_compression_filter;
301302

@@ -308,6 +309,7 @@ typedef struct cgltf_meshopt_compression
308309
cgltf_size count;
309310
cgltf_meshopt_compression_mode mode;
310311
cgltf_meshopt_compression_filter filter;
312+
cgltf_bool is_khr;
311313
} cgltf_meshopt_compression;
312314

313315
typedef struct cgltf_buffer_view
@@ -1658,8 +1660,8 @@ cgltf_result cgltf_validate(cgltf_data* data)
16581660
CGLTF_ASSERT_IF((mc->mode == cgltf_meshopt_compression_mode_triangles || mc->mode == cgltf_meshopt_compression_mode_indices) && mc->filter != cgltf_meshopt_compression_filter_none, cgltf_result_invalid_gltf);
16591661

16601662
CGLTF_ASSERT_IF(mc->filter == cgltf_meshopt_compression_filter_octahedral && mc->stride != 4 && mc->stride != 8, cgltf_result_invalid_gltf);
1661-
16621663
CGLTF_ASSERT_IF(mc->filter == cgltf_meshopt_compression_filter_quaternion && mc->stride != 8, cgltf_result_invalid_gltf);
1664+
CGLTF_ASSERT_IF(mc->filter == cgltf_meshopt_compression_filter_color && mc->stride != 4 && mc->stride != 8, cgltf_result_invalid_gltf);
16631665
}
16641666
}
16651667

@@ -5104,6 +5106,10 @@ static int cgltf_parse_json_meshopt_compression(cgltf_options* options, jsmntok_
51045106
{
51055107
out_meshopt_compression->filter = cgltf_meshopt_compression_filter_exponential;
51065108
}
5109+
else if (cgltf_json_strcmp(tokens+i, json_chunk, "COLOR") == 0)
5110+
{
5111+
out_meshopt_compression->filter = cgltf_meshopt_compression_filter_color;
5112+
}
51075113
++i;
51085114
}
51095115
else
@@ -5214,6 +5220,12 @@ static int cgltf_parse_json_buffer_view(cgltf_options* options, jsmntok_t const*
52145220
out_buffer_view->has_meshopt_compression = 1;
52155221
i = cgltf_parse_json_meshopt_compression(options, tokens, i + 1, json_chunk, &out_buffer_view->meshopt_compression);
52165222
}
5223+
else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_meshopt_compression") == 0)
5224+
{
5225+
out_buffer_view->has_meshopt_compression = 1;
5226+
out_buffer_view->meshopt_compression.is_khr = 1;
5227+
i = cgltf_parse_json_meshopt_compression(options, tokens, i + 1, json_chunk, &out_buffer_view->meshopt_compression);
5228+
}
52175229
else
52185230
{
52195231
i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_buffer_view->extensions[out_buffer_view->extensions_count++]));

‎gltf/gltfpack.cpp‎

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ std::string getVersion()
2323
return result;
2424
}
2525

26-
static void finalizeBufferViews(std::string& json, std::vector<BufferView>& views, std::string& bin, std::string* fallback, size_t& fallback_size, const char* meshopt_ext)
26+
static void finalizeBufferViews(std::string& json, std::vector<BufferView>& views, std::string& bin, std::string* fallback, size_t& fallback_size, const char* meshopt_ext, int attribute_level)
2727
{
2828
for (size_t i = 0; i < views.size(); ++i)
2929
{
@@ -43,7 +43,7 @@ static void finalizeBufferViews(std::string& json, std::vector<BufferView>& view
4343
switch (view.compression)
4444
{
4545
case BufferView::Compression_Attribute:
46-
compressVertexStream(bin, view.data, count, view.stride);
46+
compressVertexStream(bin, view.data, count, view.stride, attribute_level);
4747
break;
4848
case BufferView::Compression_Index:
4949
compressIndexStream(bin, view.data, count, view.stride);
@@ -885,7 +885,7 @@ static size_t process(cgltf_data* data, const char* input_path, const char* outp
885885
size_t bufferspec_pos = json.size();
886886

887887
std::string json_views;
888-
finalizeBufferViews(json_views, views, bin, settings.fallback ? &fallback : NULL, fallback_size, meshopt_ext);
888+
finalizeBufferViews(json_views, views, bin, settings.fallback ? &fallback : NULL, fallback_size, meshopt_ext, settings.compresskhr ? (settings.compressmore ? 3 : 2) : 0);
889889

890890
writeArray(json, "bufferViews", json_views);
891891
writeArray(json, "accessors", json_accessors);
@@ -1106,7 +1106,7 @@ int gltfpack(const char* input, const char* output, const char* report, Settings
11061106
}
11071107
}
11081108

1109-
const char* meshopt_ext = settings.compressexp ? "EXTX_meshopt_compression" : "EXT_meshopt_compression";
1109+
const char* meshopt_ext = settings.compresskhr ? "KHR_meshopt_compression" : "EXT_meshopt_compression";
11101110

11111111
std::string json, bin, fallback;
11121112
size_t fallback_size = 0;
@@ -1559,13 +1559,16 @@ int main(int argc, char** argv)
15591559
settings.compress = true;
15601560
settings.fallback = true;
15611561
}
1562-
else if (strcmp(arg, "-cx") == 0)
1562+
else if (strcmp(arg, "-cz") == 0)
15631563
{
1564-
fprintf(stderr, "Warning: experimental compression will produce files that are not compliant with EXT_meshopt_compression\n");
1565-
meshopt_encodeVertexVersion(1);
15661564
settings.compress = true;
15671565
settings.compressmore = true;
1568-
settings.compressexp = true;
1566+
settings.compresskhr = true;
1567+
}
1568+
else if (strcmp(arg, "-ce") == 0 && i + 1 < argc && (strcmp(argv[i + 1], "khr") == 0 || strcmp(argv[i + 1], "ext") == 0))
1569+
{
1570+
settings.compress = true;
1571+
settings.compresskhr = strcmp(argv[++i], "khr") == 0;
15691572
}
15701573
else if (strcmp(arg, "-v") == 0)
15711574
{
@@ -1629,7 +1632,7 @@ int main(int argc, char** argv)
16291632
fprintf(stderr, "\nBasics:\n");
16301633
fprintf(stderr, "\t-i file: input file to process, .obj/.gltf/.glb\n");
16311634
fprintf(stderr, "\t-o file: output file path, .gltf/.glb\n");
1632-
fprintf(stderr, "\t-c: produce compressed gltf/glb files (-cc for higher compression ratio)\n");
1635+
fprintf(stderr, "\t-c: produce compressed gltf/glb files (-cc/-cz for higher compression ratio)\n");
16331636
fprintf(stderr, "\nTextures:\n");
16341637
fprintf(stderr, "\t-tc: convert all textures to KTX2 with BasisU supercompression\n");
16351638
fprintf(stderr, "\t-tu: use UASTC when encoding textures (much higher quality and much larger size)\n");
@@ -1683,6 +1686,7 @@ int main(int argc, char** argv)
16831686
fprintf(stderr, "\t-mi: use EXT_mesh_gpu_instancing when serializing multiple mesh instances\n");
16841687
fprintf(stderr, "\nMiscellaneous:\n");
16851688
fprintf(stderr, "\t-cf: produce compressed gltf/glb files with fallback for loaders that don't support compression\n");
1689+
fprintf(stderr, "\t-ce ext|khr: use EXT or KHR version of meshopt compression extension for compression\n");
16861690
fprintf(stderr, "\t-noq: disable quantization; produces much larger glTF files with no extensions\n");
16871691
fprintf(stderr, "\t-v: verbose output (when used with other options)\n");
16881692
fprintf(stderr, "\t-v: print version (when used without other options)\n");
@@ -1694,7 +1698,7 @@ int main(int argc, char** argv)
16941698
fprintf(stderr, "\nBasics:\n");
16951699
fprintf(stderr, "\t-i file: input file to process, .obj/.gltf/.glb\n");
16961700
fprintf(stderr, "\t-o file: output file path, .gltf/.glb\n");
1697-
fprintf(stderr, "\t-c: produce compressed gltf/glb files (-cc for higher compression ratio)\n");
1701+
fprintf(stderr, "\t-c: produce compressed gltf/glb files (-cc/-cz for higher compression ratio)\n");
16981702
fprintf(stderr, "\t-tc: convert all textures to KTX2 with BasisU supercompression\n");
16991703
fprintf(stderr, "\t-tw: convert all textures to WebP\n");
17001704
fprintf(stderr, "\t-si R: simplify meshes targeting triangle/point count ratio R (between 0 and 1)\n");

‎gltf/gltfpack.h‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ struct Settings
173173

174174
bool compress;
175175
bool compressmore;
176-
bool compressexp;
176+
bool compresskhr;
177177
bool fallback;
178178

179179
int verbose;
@@ -379,7 +379,7 @@ StreamFormat writeIndexStream(std::string& bin, const std::vector<unsigned int>&
379379
StreamFormat writeTimeStream(std::string& bin, const std::vector<float>& data);
380380
StreamFormat writeKeyframeStream(std::string& bin, cgltf_animation_path_type type, const std::vector<Attr>& data, const Settings& settings, bool has_tangents = false);
381381

382-
void compressVertexStream(std::string& bin, const std::string& data, size_t count, size_t stride);
382+
void compressVertexStream(std::string& bin, const std::string& data, size_t count, size_t stride, int level);
383383
void compressIndexStream(std::string& bin, const std::string& data, size_t count, size_t stride);
384384
void compressIndexSequence(std::string& bin, const std::string& data, size_t count, size_t stride);
385385

‎gltf/parsegltf.cpp‎

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -552,8 +552,6 @@ static bool freeUnusedBuffers(cgltf_data* data)
552552

553553
static cgltf_result decompressMeshopt(cgltf_data* data)
554554
{
555-
bool warned = false;
556-
557555
for (size_t i = 0; i < data->buffer_views_count; ++i)
558556
{
559557
if (!data->buffer_views[i].has_meshopt_compression)
@@ -572,22 +570,18 @@ static cgltf_result decompressMeshopt(cgltf_data* data)
572570
data->buffer_views[i].data = result;
573571

574572
int rc = -1;
575-
bool warn = false;
576573

577574
switch (mc->mode)
578575
{
579576
case cgltf_meshopt_compression_mode_attributes:
580-
warn = meshopt_decodeVertexVersion(source, mc->size) != 0;
581577
rc = meshopt_decodeVertexBuffer(result, mc->count, mc->stride, source, mc->size);
582578
break;
583579

584580
case cgltf_meshopt_compression_mode_triangles:
585-
warn = meshopt_decodeIndexVersion(source, mc->size) != 1;
586581
rc = meshopt_decodeIndexBuffer(result, mc->count, mc->stride, source, mc->size);
587582
break;
588583

589584
case cgltf_meshopt_compression_mode_indices:
590-
warn = meshopt_decodeIndexVersion(source, mc->size) != 1;
591585
rc = meshopt_decodeIndexSequence(result, mc->count, mc->stride, source, mc->size);
592586
break;
593587

@@ -598,12 +592,6 @@ static cgltf_result decompressMeshopt(cgltf_data* data)
598592
if (rc != 0)
599593
return cgltf_result_io_error;
600594

601-
if (warn && !warned)
602-
{
603-
fprintf(stderr, "Warning: EXT_meshopt_compression data uses versions outside of the glTF specification (vertex 0 / index 1 expected)\n");
604-
warned = true;
605-
}
606-
607595
switch (mc->filter)
608596
{
609597
case cgltf_meshopt_compression_filter_octahedral:
@@ -618,6 +606,10 @@ static cgltf_result decompressMeshopt(cgltf_data* data)
618606
meshopt_decodeFilterExp(result, mc->count, mc->stride);
619607
break;
620608

609+
case cgltf_meshopt_compression_filter_color:
610+
meshopt_decodeFilterColor(result, mc->count, mc->stride);
611+
break;
612+
621613
default:
622614
break;
623615
}

‎gltf/stream.cpp‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -629,7 +629,7 @@ StreamFormat writeVertexStream(std::string& bin, const Stream& stream, const Qua
629629
}
630630
else if (stream.type == cgltf_attribute_type_color)
631631
{
632-
bool col = filters && settings.compressexp && settings.compressmore;
632+
bool col = filters && settings.compresskhr && settings.compressmore;
633633
int bits = settings.col_bits;
634634

635635
StreamFormat::Filter filter = col ? StreamFormat::Filter_Color : StreamFormat::Filter_None;
@@ -866,12 +866,12 @@ StreamFormat writeKeyframeStream(std::string& bin, cgltf_animation_path_type typ
866866
}
867867
}
868868

869-
void compressVertexStream(std::string& bin, const std::string& data, size_t count, size_t stride)
869+
void compressVertexStream(std::string& bin, const std::string& data, size_t count, size_t stride, int level)
870870
{
871871
assert(data.size() == count * stride);
872872

873873
std::vector<unsigned char> compressed(meshopt_encodeVertexBufferBound(count, stride));
874-
size_t size = meshopt_encodeVertexBuffer(&compressed[0], compressed.size(), data.c_str(), count, stride);
874+
size_t size = meshopt_encodeVertexBufferLevel(&compressed[0], compressed.size(), data.c_str(), count, stride, level, level > 0);
875875

876876
bin.append(reinterpret_cast<const char*>(&compressed[0]), size);
877877
}

0 commit comments

Comments
 (0)