Updated meshoptimizer.

This commit is contained in:
Бранимир Караџић 2019-11-13 07:24:59 -08:00
parent 829fb28f4c
commit 126c0d6596
6 changed files with 93 additions and 26 deletions

View File

@ -17,6 +17,7 @@ jobs:
make -j2 config=debug test
make -j2 config=release test
make -j2 config=release gltfpack
strip gltfpack
- name: make coverage
run: |
make -j2 config=coverage test
@ -36,7 +37,7 @@ jobs:
steps:
- uses: actions/checkout@v1
- name: cmake configure
run: cmake . -DBUILD_DEMO=ON -DBUILD_TOOLS=ON -A ${{matrix.arch}}
run: cmake . -DBUILD_DEMO=ON -DBUILD_TOOLS=ON -DCMAKE_MSVC_RUNTIME_LIBRARY="MultiThreaded$<$<CONFIG:Debug>:Debug>" -A ${{matrix.arch}}
- name: cmake test
shell: bash # necessary for fail-fast
run: |
@ -48,3 +49,4 @@ jobs:
with:
name: gltfpack-windows
path: Release/gltfpack.exe
if: matrix.arch == 'x64'

View File

@ -1,6 +1,7 @@
language: cpp
jobs:
include:
- os: linux
compiler: gcc
- os: linux

View File

@ -1,5 +1,10 @@
cmake_minimum_required(VERSION 3.0)
if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.15)
cmake_policy(SET CMP0091 NEW) # Enables use of MSVC_RUNTIME_LIBRARY
cmake_policy(SET CMP0092 NEW) # Enables clean /W4 override for MSVC
endif()
project(meshoptimizer VERSION 0.12 LANGUAGES CXX)
option(BUILD_DEMO "Build demo" OFF)

View File

@ -33,6 +33,7 @@
var canvas = document.getElementById("renderCanvas");
BABYLON.GLTF2.GLTFLoader.RegisterExtension("MESHOPT_compression", (loader) => new MESHOPT_compression(loader, MeshoptDecoder));
BABYLON.GLTF2.GLTFLoader.RegisterExtension("KHR_quantized_geometry", (loader) => ({ name: "KHR_quantized_geometry", enabled: true }));
var createScene = function () {
var scene = new BABYLON.Scene(engine);

Binary file not shown.

View File

@ -73,7 +73,7 @@ struct Settings
int pos_bits;
int tex_bits;
int nrm_bits;
bool nrm_unit;
bool nrm_unnormalized;
int anim_freq;
bool anim_const;
@ -841,6 +841,29 @@ void reindexMesh(Mesh& mesh)
}
}
void filterMesh(Mesh& mesh)
{
unsigned int* indices = &mesh.indices[0];
size_t total_indices = mesh.indices.size();
size_t write = 0;
for (size_t i = 0; i < total_indices; i += 3)
{
unsigned int a = indices[i + 0], b = indices[i + 1], c = indices[i + 2];
if (a != b && a != c && b != c)
{
indices[write + 0] = a;
indices[write + 1] = b;
indices[write + 2] = c;
write += 3;
}
}
mesh.indices.resize(write);
}
Stream* getStream(Mesh& mesh, cgltf_attribute_type type)
{
for (size_t i = 0; i < mesh.streams.size(); ++i)
@ -922,6 +945,9 @@ void sortBoneInfluences(Mesh& mesh)
if (!joints || !weights)
return;
// weights below cutoff can't be represented in quantized 8-bit storage
const float weight_cutoff = 0.5f / 255.f;
size_t vertex_count = mesh.streams[0].data.size();
for (size_t i = 0; i < vertex_count; ++i)
@ -933,7 +959,7 @@ void sortBoneInfluences(Mesh& mesh)
int count = 0;
for (int k = 0; k < 4; ++k)
if (wa.f[k] > 0.f)
if (wa.f[k] > weight_cutoff)
{
inf[count].i = ja.f[k];
inf[count].w = wa.f[k];
@ -1156,20 +1182,51 @@ StreamFormat writeVertexStream(std::string& bin, const Stream& stream, const Qua
{
float pos_rscale = params.pos_scale == 0.f ? 0.f : 1.f / params.pos_scale;
int maxv = 0;
for (size_t i = 0; i < stream.data.size(); ++i)
{
const Attr& a = stream.data[i];
int16_t v[4] = {
int16_t((a.f[0] >= 0.f ? 1 : -1) * meshopt_quantizeUnorm(fabsf(a.f[0]) * pos_rscale, params.pos_bits)),
int16_t((a.f[1] >= 0.f ? 1 : -1) * meshopt_quantizeUnorm(fabsf(a.f[1]) * pos_rscale, params.pos_bits)),
int16_t((a.f[2] >= 0.f ? 1 : -1) * meshopt_quantizeUnorm(fabsf(a.f[2]) * pos_rscale, params.pos_bits)),
0};
bin.append(reinterpret_cast<const char*>(v), sizeof(v));
maxv = std::max(maxv, meshopt_quantizeUnorm(fabsf(a.f[0]) * pos_rscale, params.pos_bits));
maxv = std::max(maxv, meshopt_quantizeUnorm(fabsf(a.f[1]) * pos_rscale, params.pos_bits));
maxv = std::max(maxv, meshopt_quantizeUnorm(fabsf(a.f[2]) * pos_rscale, params.pos_bits));
}
StreamFormat format = {cgltf_type_vec3, cgltf_component_type_r_16, false, 8};
return format;
if (maxv <= 127)
{
for (size_t i = 0; i < stream.data.size(); ++i)
{
const Attr& a = stream.data[i];
int8_t v[4] = {
int8_t((a.f[0] >= 0.f ? 1 : -1) * meshopt_quantizeUnorm(fabsf(a.f[0]) * pos_rscale, params.pos_bits)),
int8_t((a.f[1] >= 0.f ? 1 : -1) * meshopt_quantizeUnorm(fabsf(a.f[1]) * pos_rscale, params.pos_bits)),
int8_t((a.f[2] >= 0.f ? 1 : -1) * meshopt_quantizeUnorm(fabsf(a.f[2]) * pos_rscale, params.pos_bits)),
0};
bin.append(reinterpret_cast<const char*>(v), sizeof(v));
}
StreamFormat format = {cgltf_type_vec3, cgltf_component_type_r_8, false, 4};
return format;
}
else
{
for (size_t i = 0; i < stream.data.size(); ++i)
{
const Attr& a = stream.data[i];
int16_t v[4] = {
int16_t((a.f[0] >= 0.f ? 1 : -1) * meshopt_quantizeUnorm(fabsf(a.f[0]) * pos_rscale, params.pos_bits)),
int16_t((a.f[1] >= 0.f ? 1 : -1) * meshopt_quantizeUnorm(fabsf(a.f[1]) * pos_rscale, params.pos_bits)),
int16_t((a.f[2] >= 0.f ? 1 : -1) * meshopt_quantizeUnorm(fabsf(a.f[2]) * pos_rscale, params.pos_bits)),
0};
bin.append(reinterpret_cast<const char*>(v), sizeof(v));
}
StreamFormat format = {cgltf_type_vec3, cgltf_component_type_r_16, false, 8};
return format;
}
}
}
else if (stream.type == cgltf_attribute_type_texcoord)
@ -1195,8 +1252,8 @@ StreamFormat writeVertexStream(std::string& bin, const Stream& stream, const Qua
}
else if (stream.type == cgltf_attribute_type_normal)
{
bool nrm_unit = has_targets || settings.nrm_unit;
int bits = nrm_unit ? (settings.nrm_bits > 8 ? 16 : 8) : settings.nrm_bits;
bool unnormalized = settings.nrm_unnormalized && !has_targets;
int bits = unnormalized ? settings.nrm_bits : (settings.nrm_bits > 8 ? 16 : 8);
for (size_t i = 0; i < stream.data.size(); ++i)
{
@ -1204,7 +1261,7 @@ StreamFormat writeVertexStream(std::string& bin, const Stream& stream, const Qua
float nx = a.f[0], ny = a.f[1], nz = a.f[2];
if (!nrm_unit)
if (unnormalized)
rescaleNormal(nx, ny, nz);
if (bits > 8)
@ -1240,8 +1297,8 @@ StreamFormat writeVertexStream(std::string& bin, const Stream& stream, const Qua
}
else if (stream.type == cgltf_attribute_type_tangent)
{
bool nrm_unit = has_targets || settings.nrm_unit;
int bits = nrm_unit ? (settings.nrm_bits > 8 ? 16 : 8) : settings.nrm_bits;
bool unnormalized = settings.nrm_unnormalized && !has_targets;
int bits = unnormalized ? settings.nrm_bits : (settings.nrm_bits > 8 ? 16 : 8);
for (size_t i = 0; i < stream.data.size(); ++i)
{
@ -1249,7 +1306,7 @@ StreamFormat writeVertexStream(std::string& bin, const Stream& stream, const Qua
float nx = a.f[0], ny = a.f[1], nz = a.f[2], nw = a.f[3];
if (!nrm_unit)
if (unnormalized)
rescaleNormal(nx, ny, nz);
if (bits > 8)
@ -3143,6 +3200,7 @@ void process(cgltf_data* data, std::vector<Mesh>& meshes, const Settings& settin
case cgltf_primitive_type_triangles:
reindexMesh(mesh);
filterMesh(mesh);
simplifyMesh(mesh, settings.simplify_threshold, settings.simplify_aggressive);
optimizeMesh(mesh);
sortBoneInfluences(mesh);
@ -3443,8 +3501,9 @@ void process(cgltf_data* data, std::vector<Mesh>& meshes, const Settings& settin
json.append(data->json + data->asset.extras.start_offset, data->json + data->asset.extras.end_offset);
}
append(json, "}");
append(json, ",\"extensionsUsed\":[");
append(json, "\"MESHOPT_quantized_geometry\"");
append(json, "\"KHR_quantized_geometry\"");
if (settings.compress)
{
comma(json);
@ -3471,16 +3530,15 @@ void process(cgltf_data* data, std::vector<Mesh>& meshes, const Settings& settin
append(json, "\"KHR_lights_punctual\"");
}
append(json, "]");
append(json, ",\"extensionsRequired\":[");
append(json, "\"KHR_quantized_geometry\"");
if (settings.compress && !settings.fallback)
{
append(json, ",\"extensionsRequired\":[");
// Note: ideally we should include MESHOPT_quantized_geometry in the required extension list (regardless of compression)
// This extension *only* allows the use of quantized attributes for positions/normals/etc. This happens to be supported
// by popular JS frameworks, however, Babylon.JS refuses to load files with unsupported required extensions.
// For now we don't include it in the list, which will be fixed at some point once this extension becomes official.
comma(json);
append(json, "\"MESHOPT_compression\"");
append(json, "]");
}
append(json, "]");
if (!views.empty())
{
@ -3833,7 +3891,7 @@ int main(int argc, char** argv)
}
else if (strcmp(arg, "-vu") == 0)
{
settings.nrm_unit = true;
settings.nrm_unnormalized = true;
}
else if (strcmp(arg, "-af") == 0 && i + 1 < argc && isdigit(argv[i + 1][0]))
{
@ -3917,7 +3975,7 @@ int main(int argc, char** argv)
fprintf(stderr, "-vp N: use N-bit quantization for positions (default: 14; N should be between 1 and 16)\n");
fprintf(stderr, "-vt N: use N-bit quantization for texture corodinates (default: 12; N should be between 1 and 16)\n");
fprintf(stderr, "-vn N: use N-bit quantization for normals and tangents (default: 8; N should be between 1 and 16)\n");
fprintf(stderr, "-vu: use unit-length normal/tangent vectors (default: off)\n");
fprintf(stderr, "-vu: use unnormalized normal/tangent vectors to improve compression (default: off)\n");
fprintf(stderr, "-af N: resample animations at N Hz (default: 30)\n");
fprintf(stderr, "-ac: keep constant animation tracks even if they don't modify the node transform\n");
fprintf(stderr, "-kn: keep named nodes and meshes attached to named nodes so that named nodes can be transformed externally\n");