diff --git a/examples/assets/meshes/meshes.ninja b/examples/assets/meshes/meshes.ninja index cc88f052a..9ebfc52af 100644 --- a/examples/assets/meshes/meshes.ninja +++ b/examples/assets/meshes/meshes.ninja @@ -1,18 +1,18 @@ meshes = $pwd/../../runtime/meshes build $meshes/bunny.bin: geometryc_pack_normal_barycentric $pwd/bunny.obj -build $meshes/bunny_decimated.bin: geometryc_pack_normal $pwd/bunny_decimated.obj +build $meshes/bunny_decimated.bin: geometryc_pack_normal_compressed $pwd/bunny_decimated.obj build $meshes/bunny_patched.bin: geometryc_pack_normal $pwd/bunny_patched.obj build $meshes/column.bin: geometryc_pack_normal $pwd/column.obj build $meshes/cube.bin: geometryc_pack_normal $pwd/cube.obj build $meshes/hollowcube.bin: geometryc_pack_normal_barycentric $pwd/hollowcube.obj build $meshes/orb.bin: geometryc_pack_normal_barycentric $pwd/orb.obj build $meshes/platform.bin: geometryc_pack_normal $pwd/platform.obj -build $meshes/tree.bin: geometryc_pack_normal $pwd/tree.obj -build $meshes/tree1b_lod0_1.bin: geometryc_pack_normal $pwd/tree1b_lod0_1.obj -build $meshes/tree1b_lod0_2.bin: geometryc_pack_normal $pwd/tree1b_lod0_2.obj -build $meshes/tree1b_lod1_1.bin: geometryc_pack_normal $pwd/tree1b_lod1_1.obj -build $meshes/tree1b_lod1_2.bin: geometryc_pack_normal $pwd/tree1b_lod1_2.obj -build $meshes/tree1b_lod2_1.bin: geometryc_pack_normal $pwd/tree1b_lod2_1.obj -build $meshes/tree1b_lod2_2.bin: geometryc_pack_normal $pwd/tree1b_lod2_2.obj +build $meshes/tree.bin: geometryc_pack_normal_compressed $pwd/tree.obj +build $meshes/tree1b_lod0_1.bin: geometryc_pack_normal_compressed $pwd/tree1b_lod0_1.obj +build $meshes/tree1b_lod0_2.bin: geometryc_pack_normal_compressed $pwd/tree1b_lod0_2.obj +build $meshes/tree1b_lod1_1.bin: geometryc_pack_normal_compressed $pwd/tree1b_lod1_1.obj +build $meshes/tree1b_lod1_2.bin: geometryc_pack_normal_compressed $pwd/tree1b_lod1_2.obj +build $meshes/tree1b_lod2_1.bin: geometryc_pack_normal_compressed $pwd/tree1b_lod2_1.obj +build $meshes/tree1b_lod2_2.bin: geometryc_pack_normal_compressed $pwd/tree1b_lod2_2.obj build $meshes/test_scene.bin: geometryc_pack_normal $pwd/../sky/test_scene.obj diff --git a/examples/common/bgfx_utils.cpp b/examples/common/bgfx_utils.cpp index 5836e4d7b..9bc1e193d 100644 --- a/examples/common/bgfx_utils.cpp +++ b/examples/common/bgfx_utils.cpp @@ -17,7 +17,7 @@ namespace stl = tinystl; #include #include #include "entry/entry.h" -#include +#include #include "bgfx_utils.h" @@ -418,8 +418,9 @@ struct Mesh void load(bx::ReaderSeekerI* _reader) { #define BGFX_CHUNK_MAGIC_VB BX_MAKEFOURCC('V', 'B', ' ', 0x1) +#define BGFX_CHUNK_MAGIC_VBC BX_MAKEFOURCC('V', 'B', 'C', 0x0) #define BGFX_CHUNK_MAGIC_IB BX_MAKEFOURCC('I', 'B', ' ', 0x0) -#define BGFX_CHUNK_MAGIC_IBC BX_MAKEFOURCC('I', 'B', 'C', 0x0) +#define BGFX_CHUNK_MAGIC_IBC BX_MAKEFOURCC('I', 'B', 'C', 0x1) #define BGFX_CHUNK_MAGIC_PRI BX_MAKEFOURCC('P', 'R', 'I', 0x0) using namespace bx; @@ -454,6 +455,34 @@ struct Mesh group.m_vbh = bgfx::createVertexBuffer(mem, m_decl); } break; + case BGFX_CHUNK_MAGIC_VBC: + { + read(_reader, group.m_sphere); + read(_reader, group.m_aabb); + read(_reader, group.m_obb); + + read(_reader, m_decl); + + uint16_t stride = m_decl.getStride(); + + uint16_t numVertices; + read(_reader, numVertices); + + const bgfx::Memory* mem = bgfx::alloc(numVertices*stride); + + uint32_t compressedSize; + bx::read(_reader, compressedSize); + + void* compressedVertices = BX_ALLOC(allocator, compressedSize); + bx::read(_reader, compressedVertices, compressedSize); + + meshopt_decodeVertexBuffer(mem->data, numVertices, stride, (uint8_t*)compressedVertices, compressedSize); + + BX_FREE(allocator, compressedVertices); + + group.m_vbh = bgfx::createVertexBuffer(mem, m_decl); + } + break; case BGFX_CHUNK_MAGIC_IB: { @@ -479,8 +508,7 @@ struct Mesh bx::read(_reader, compressedIndices, compressedSize); - ReadBitstream rbs( (const uint8_t*)compressedIndices, compressedSize); - DecompressIndexBuffer( (uint16_t*)mem->data, numIndices / 3, rbs); + meshopt_decodeIndexBuffer(mem->data, numIndices, 2, (uint8_t*)compressedIndices, compressedSize); BX_FREE(allocator, compressedIndices); diff --git a/examples/runtime/meshes/bunny.bin b/examples/runtime/meshes/bunny.bin index f0fed0880..ef3127bc7 100644 Binary files a/examples/runtime/meshes/bunny.bin and b/examples/runtime/meshes/bunny.bin differ diff --git a/examples/runtime/meshes/bunny_patched.bin b/examples/runtime/meshes/bunny_patched.bin index e8645370e..3af10d214 100644 Binary files a/examples/runtime/meshes/bunny_patched.bin and b/examples/runtime/meshes/bunny_patched.bin differ diff --git a/examples/runtime/meshes/column.bin b/examples/runtime/meshes/column.bin index a58c780d1..cd0ebabd1 100644 Binary files a/examples/runtime/meshes/column.bin and b/examples/runtime/meshes/column.bin differ diff --git a/examples/runtime/meshes/hollowcube.bin b/examples/runtime/meshes/hollowcube.bin index 1ed9d7cc9..e45df2cd9 100644 Binary files a/examples/runtime/meshes/hollowcube.bin and b/examples/runtime/meshes/hollowcube.bin differ diff --git a/examples/runtime/meshes/orb.bin b/examples/runtime/meshes/orb.bin index ff8d16628..034ad0756 100644 Binary files a/examples/runtime/meshes/orb.bin and b/examples/runtime/meshes/orb.bin differ diff --git a/examples/runtime/meshes/platform.bin b/examples/runtime/meshes/platform.bin index de63c2457..6e5a46395 100644 Binary files a/examples/runtime/meshes/platform.bin and b/examples/runtime/meshes/platform.bin differ diff --git a/examples/runtime/meshes/test_scene.bin b/examples/runtime/meshes/test_scene.bin index bf234cb0b..95e810c1c 100644 Binary files a/examples/runtime/meshes/test_scene.bin and b/examples/runtime/meshes/test_scene.bin differ diff --git a/examples/runtime/meshes/tree1b_lod0_1.bin b/examples/runtime/meshes/tree1b_lod0_1.bin index 26ed0727b..cfee4c08b 100644 Binary files a/examples/runtime/meshes/tree1b_lod0_1.bin and b/examples/runtime/meshes/tree1b_lod0_1.bin differ diff --git a/examples/runtime/meshes/tree1b_lod0_2.bin b/examples/runtime/meshes/tree1b_lod0_2.bin index 97f939dbd..5c6398e63 100644 Binary files a/examples/runtime/meshes/tree1b_lod0_2.bin and b/examples/runtime/meshes/tree1b_lod0_2.bin differ diff --git a/examples/runtime/meshes/tree1b_lod1_1.bin b/examples/runtime/meshes/tree1b_lod1_1.bin index 563e82c91..c041fd83e 100644 Binary files a/examples/runtime/meshes/tree1b_lod1_1.bin and b/examples/runtime/meshes/tree1b_lod1_1.bin differ diff --git a/examples/runtime/meshes/tree1b_lod1_2.bin b/examples/runtime/meshes/tree1b_lod1_2.bin index 1983f8360..ddf038c34 100644 Binary files a/examples/runtime/meshes/tree1b_lod1_2.bin and b/examples/runtime/meshes/tree1b_lod1_2.bin differ diff --git a/examples/runtime/meshes/tree1b_lod2_1.bin b/examples/runtime/meshes/tree1b_lod2_1.bin index d2aa057f6..a61a7f86e 100644 Binary files a/examples/runtime/meshes/tree1b_lod2_1.bin and b/examples/runtime/meshes/tree1b_lod2_1.bin differ diff --git a/examples/runtime/meshes/tree1b_lod2_2.bin b/examples/runtime/meshes/tree1b_lod2_2.bin index 886d7b3be..d061509b7 100644 Binary files a/examples/runtime/meshes/tree1b_lod2_2.bin and b/examples/runtime/meshes/tree1b_lod2_2.bin differ diff --git a/scripts/build.ninja b/scripts/build.ninja index 1cfcac5c4..1f0239869 100644 --- a/scripts/build.ninja +++ b/scripts/build.ninja @@ -4,6 +4,10 @@ rule geometryc_pack_normal command = geometryc -f $in -o $out --packnormal 1 description = Converting geometry $in... +rule geometryc_pack_normal_compressed + command = geometryc -f $in -o $out --packnormal 1 -c + description = Converting geometry $in... + rule geometryc_pack_normal_barycentric command = geometryc -f $in -o $out --packnormal 1 --barycentric description = Converting geometry $in... diff --git a/scripts/example-common.lua b/scripts/example-common.lua index 40b91c83b..f14bf5d41 100644 --- a/scripts/example-common.lua +++ b/scripts/example-common.lua @@ -28,8 +28,8 @@ project ("example-common") } files { - path.join(BGFX_DIR, "3rdparty/ib-compress/**.cpp"), - path.join(BGFX_DIR, "3rdparty/ib-compress/**.h"), + path.join(BGFX_DIR, "3rdparty/meshoptimizer/src/**.cpp"), + path.join(BGFX_DIR, "3rdparty/meshoptimizer/src/**.h"), path.join(BGFX_DIR, "3rdparty/dear-imgui/**.cpp"), path.join(BGFX_DIR, "3rdparty/dear-imgui/**.h"), path.join(BGFX_DIR, "examples/common/**.cpp"), diff --git a/scripts/geometryc.lua b/scripts/geometryc.lua index 44900426a..9fdd895c8 100644 --- a/scripts/geometryc.lua +++ b/scripts/geometryc.lua @@ -15,10 +15,8 @@ project "geometryc" } files { - path.join(BGFX_DIR, "3rdparty/forsyth-too/**.cpp"), - path.join(BGFX_DIR, "3rdparty/forsyth-too/**.h"), - path.join(BGFX_DIR, "3rdparty/ib-compress/**.cpp"), - path.join(BGFX_DIR, "3rdparty/ib-compress/**.h"), + path.join(BGFX_DIR, "3rdparty/meshoptimizer/src/**.cpp"), + path.join(BGFX_DIR, "3rdparty/meshoptimizer/src/**.h"), path.join(BGFX_DIR, "src/vertexdecl.**"), path.join(BGFX_DIR, "tools/geometryc/**.cpp"), path.join(BGFX_DIR, "tools/geometryc/**.h"), diff --git a/tools/geometryc/geometryc.cpp b/tools/geometryc/geometryc.cpp index 32c947d98..64909379d 100644 --- a/tools/geometryc/geometryc.cpp +++ b/tools/geometryc/geometryc.cpp @@ -18,8 +18,7 @@ #include namespace stl = tinystl; -#include -#include +#include #define BGFX_GEOMETRYC_VERSION_MAJOR 1 #define BGFX_GEOMETRYC_VERSION_MINOR 0 @@ -103,8 +102,9 @@ typedef std::vector PrimitiveArray; static uint32_t s_obbSteps = 17; #define BGFX_CHUNK_MAGIC_VB BX_MAKEFOURCC('V', 'B', ' ', 0x1) +#define BGFX_CHUNK_MAGIC_VBC BX_MAKEFOURCC('V', 'B', 'C', 0x0) #define BGFX_CHUNK_MAGIC_IB BX_MAKEFOURCC('I', 'B', ' ', 0x0) -#define BGFX_CHUNK_MAGIC_IBC BX_MAKEFOURCC('I', 'B', 'C', 0x0) +#define BGFX_CHUNK_MAGIC_IBC BX_MAKEFOURCC('I', 'B', 'C', 0x1) #define BGFX_CHUNK_MAGIC_PRI BX_MAKEFOURCC('P', 'R', 'I', 0x0) long int fsize(FILE* _file) @@ -116,41 +116,54 @@ long int fsize(FILE* _file) return size; } -void triangleReorder(uint16_t* _indices, uint32_t _numIndices, uint32_t _numVertices, uint16_t _cacheSize) +void optimizeVertexCache(uint16_t* _indices, uint32_t _numIndices, uint32_t _numVertices) { uint16_t* newIndexList = new uint16_t[_numIndices]; - Forsyth::OptimizeFaces(_indices, _numIndices, _numVertices, 0, newIndexList, _cacheSize); - bx::memCopy(_indices, newIndexList, _numIndices*2); - delete [] newIndexList; + meshopt_optimizeVertexCache(newIndexList, _indices, _numIndices, _numVertices); + bx::memCopy(_indices, newIndexList, _numIndices * 2); + delete[] newIndexList; } -void triangleCompress(bx::WriterI* _writer, uint16_t* _indices, uint32_t _numIndices, uint8_t* _vertexData, uint32_t _numVertices, uint16_t _stride) +uint32_t optimizeVertexFetch(uint16_t* _indices, uint32_t _numIndices, uint8_t* _vertexData, uint32_t _numVertices, uint16_t _stride) { - uint32_t* vertexRemap = (uint32_t*)malloc(_numVertices*sizeof(uint32_t) ); + unsigned char* newVertices = (unsigned char*)malloc(_numVertices * _stride ); + size_t vertexCount = meshopt_optimizeVertexFetch(newVertices, _indices, _numIndices, _vertexData, _numVertices, _stride); + bx::memCopy(_vertexData, newVertices, _numVertices * _stride); + free(newVertices); - WriteBitstream writer; - CompressIndexBuffer(_indices, _numIndices/3, vertexRemap, _numVertices, IBCF_AUTO, writer); - writer.Finish(); - printf( "uncompressed: %10d, compressed: %10d, ratio: %0.2f%%\n" + return uint32_t(vertexCount); +} + +void writeCompressedIndices(bx::WriterI* _writer, const uint16_t* _indices, uint32_t _numIndices, uint32_t _numVertices) +{ + size_t maxSize = meshopt_encodeIndexBufferBound(_numIndices, _numVertices); + unsigned char* compressedIndices = (unsigned char*)malloc(maxSize); + size_t compressedSize = meshopt_encodeIndexBuffer(compressedIndices, maxSize, _indices, _numIndices); + printf( "indices uncompressed: %10d, compressed: %10d, ratio: %0.2f%%\n" , _numIndices*2 - , (uint32_t)writer.ByteSize() - , 100.0f - float(writer.ByteSize() ) / float(_numIndices*2)*100.0f - ); + , (uint32_t)compressedSize + , 100.0f - float(compressedSize ) / float(_numIndices*2)*100.0f + ); - BX_UNUSED(_vertexData, _stride); - uint8_t* outVertexData = (uint8_t*)malloc(_numVertices*_stride); - for (uint32_t ii = 0; ii < _numVertices; ++ii) - { - uint32_t remap = vertexRemap[ii]; - remap = UINT32_MAX == remap ? ii : remap; - bx::memCopy(&outVertexData[remap*_stride], &_vertexData[ii*_stride], _stride); - } - bx::memCopy(_vertexData, outVertexData, _numVertices*_stride); - free(outVertexData); + bx::write(_writer, (uint32_t)compressedSize); + bx::write(_writer, compressedIndices, (uint32_t)compressedSize ); + free(compressedIndices); +} - free(vertexRemap); +void writeCompressedVertices(bx::WriterI* _writer, const uint8_t* _vertices, uint32_t _numVertices, uint16_t _stride) +{ + size_t maxSize = meshopt_encodeVertexBufferBound(_numVertices, _stride); + unsigned char* compressedVertices = (unsigned char*)malloc(maxSize); + size_t compressedSize = meshopt_encodeVertexBuffer(compressedVertices, maxSize, _vertices, _numVertices, _stride); + printf("vertices uncompressed: %10d, compressed: %10d, ratio: %0.2f%%\n" + , _numVertices * _stride + , (uint32_t)compressedSize + , 100.0f - float(compressedSize) / float(_numVertices * _stride)*100.0f + ); - bx::write(_writer, writer.RawData(), (uint32_t)writer.ByteSize() ); + bx::write(_writer, (uint32_t)compressedSize); + bx::write(_writer, compressedVertices, (uint32_t)compressedSize ); + free(compressedVertices); } void calcTangents(void* _vertices, uint16_t _numVertices, bgfx::VertexDecl _decl, const uint16_t* _indices, uint32_t _numIndices) @@ -282,8 +295,7 @@ void write(bx::WriterI* _writer , const bgfx::VertexDecl& _decl , const uint16_t* _indices , uint32_t _numIndices - , const uint8_t* _compressedIndices - , uint32_t _compressedSize + , bool _compress , const stl::string& _material , const PrimitiveArray& _primitives ) @@ -292,20 +304,33 @@ void write(bx::WriterI* _writer using namespace bgfx; uint32_t stride = _decl.getStride(); - write(_writer, BGFX_CHUNK_MAGIC_VB); - write(_writer, _vertices, _numVertices, stride); - write(_writer, _decl); + if (_compress) + { + write(_writer, BGFX_CHUNK_MAGIC_VBC); + write(_writer, _vertices, _numVertices, stride); - write(_writer, uint16_t(_numVertices) ); - write(_writer, _vertices, _numVertices*stride); + write(_writer, _decl); - if (NULL != _compressedIndices) + write(_writer, uint16_t(_numVertices) ); + writeCompressedVertices(_writer, _vertices, _numVertices, uint16_t(stride)); + } + else + { + write(_writer, BGFX_CHUNK_MAGIC_VB); + write(_writer, _vertices, _numVertices, stride); + + write(_writer, _decl); + + write(_writer, uint16_t(_numVertices) ); + write(_writer, _vertices, _numVertices*stride); + } + + if (_compress) { write(_writer, BGFX_CHUNK_MAGIC_IBC); write(_writer, _numIndices); - write(_writer, _compressedSize); - write(_writer, _compressedIndices, _compressedSize); + writeCompressedIndices(_writer, _indices, _numIndices, _numVertices); } else { @@ -682,7 +707,7 @@ int main(int _argc, const char* _argv[]) bx::fromString(&py, argv[2]); bx::fromString(&pz, argv[3]); - if (argc > 4) + if (argc == 5 || argc == 8) { bx::fromString(&pw, argv[4]); } @@ -854,7 +879,10 @@ int main(int _argc, const char* _argv[]) uint16_t* indexData = new uint16_t[triangles.size() * 3]; int32_t numVertices = 0; int32_t numIndices = 0; - int32_t numPrimitives = 0; + + int32_t writtenPrimitives = 0; + int32_t writtenVertices = 0; + int32_t writtenIndices = 0; uint8_t* vertices = vertexData; uint16_t* indices = indexData; @@ -877,15 +905,19 @@ int main(int _argc, const char* _argv[]) uint32_t positionOffset = decl.getOffset(bgfx::Attrib::Position); uint32_t color0Offset = decl.getOffset(bgfx::Attrib::Color0); - bx::DefaultAllocator crtAllocator; - bx::MemoryBlock memBlock(&crtAllocator); + Group sentinelGroup; + sentinelGroup.m_startTriangle = 0; + sentinelGroup.m_numTriangles = UINT32_MAX; + groups.push_back(sentinelGroup); uint32_t ii = 0; for (GroupArray::const_iterator groupIt = groups.begin(); groupIt != groups.end(); ++groupIt, ++ii) { + bool sentinel = groupIt->m_startTriangle == 0 && groupIt->m_numTriangles == UINT32_MAX; for (uint32_t tri = groupIt->m_startTriangle, end = tri + groupIt->m_numTriangles; tri < end; ++tri) { if (0 != bx::strCmp(material.c_str(), groupIt->m_material.c_str() ) + || sentinel || 65533 <= numVertices) { prim.m_numVertices = numVertices - prim.m_startVertex; @@ -900,25 +932,14 @@ int main(int _argc, const char* _argv[]) calcTangents(vertexData, uint16_t(numVertices), decl, indexData, numIndices); } - bx::MemoryWriter memWriter(&memBlock); - triReorderElapsed -= bx::getHPCounter(); for (PrimitiveArray::const_iterator primIt = primitives.begin(); primIt != primitives.end(); ++primIt) { const Primitive& prim1 = *primIt; - triangleReorder(indexData + prim1.m_startIndex, prim1.m_numIndices, numVertices, 32); - if (compress) - { - triangleCompress( - &memWriter - , indexData + prim1.m_startIndex - , prim1.m_numIndices - , vertexData + prim1.m_startVertex - , numVertices - , uint16_t(stride) - ); - } + optimizeVertexCache(indexData + prim1.m_startIndex, prim1.m_numIndices, numVertices); } + numVertices = optimizeVertexFetch(indexData, numIndices, vertexData, numVertices, uint16_t(stride)); + triReorderElapsed += bx::getHPCounter(); write(&writer @@ -927,8 +948,7 @@ int main(int _argc, const char* _argv[]) , decl , indexData , numIndices - , (uint8_t*)memBlock.more() - , memBlock.getSize() + , compress , material , primitives ); @@ -939,15 +959,21 @@ int main(int _argc, const char* _argv[]) indexIt->second.m_vertexIndex = -1; } + ++writtenPrimitives; + writtenVertices += numVertices; + writtenIndices += numIndices; + vertices = vertexData; indices = indexData; numVertices = 0; numIndices = 0; prim.m_startVertex = 0; prim.m_startIndex = 0; - ++numPrimitives; material = groupIt->m_material; + + if (sentinel) + break; } TriIndices& triangle = triangles[tri]; @@ -1025,45 +1051,7 @@ int main(int _argc, const char* _argv[]) ); } - if (0 < primitives.size() ) - { - if (hasTangent) - { - calcTangents(vertexData, uint16_t(numVertices), decl, indexData, numIndices); - } - - bx::MemoryWriter memWriter(&memBlock); - - triReorderElapsed -= bx::getHPCounter(); - for (PrimitiveArray::const_iterator primIt = primitives.begin(); primIt != primitives.end(); ++primIt) - { - const Primitive& prim1 = *primIt; - triangleReorder(indexData + prim1.m_startIndex, prim1.m_numIndices, numVertices, 32); - if (compress) - { - triangleCompress(&memWriter - , indexData + prim1.m_startIndex - , prim1.m_numIndices - , vertexData + prim1.m_startVertex - , numVertices - , uint16_t(stride) - ); - } - } - triReorderElapsed += bx::getHPCounter(); - - write(&writer - , vertexData - , numVertices - , decl - , indexData - , numIndices - , (uint8_t*)memBlock.more() - , memBlock.getSize() - , material - , primitives - ); - } + BX_CHECK(0 == primitives.size(), "Not all primitives are written"); printf("size: %d\n", uint32_t(bx::seek(&writer) ) ); bx::close(&writer); @@ -1080,9 +1068,9 @@ int main(int _argc, const char* _argv[]) , double(convertElapsed)/bx::getHPFrequency() , num , uint32_t(groups.size() ) - , numPrimitives - , numVertices - , numIndices + , writtenPrimitives + , writtenVertices + , writtenIndices ); return bx::kExitSuccess;