diff options
Diffstat (limited to '3rdparty/bgfx/tools/geometryc/geometryc.cpp')
-rw-r--r-- | 3rdparty/bgfx/tools/geometryc/geometryc.cpp | 552 |
1 files changed, 268 insertions, 284 deletions
diff --git a/3rdparty/bgfx/tools/geometryc/geometryc.cpp b/3rdparty/bgfx/tools/geometryc/geometryc.cpp index 1e1f175e102..71eb22547a9 100644 --- a/3rdparty/bgfx/tools/geometryc/geometryc.cpp +++ b/3rdparty/bgfx/tools/geometryc/geometryc.cpp @@ -1,25 +1,20 @@ /* - * Copyright 2011-2018 Branimir Karadzic. All rights reserved. + * Copyright 2011-2019 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause */ -#include <stdio.h> - #include <algorithm> -#include <vector> #include <bx/string.h> #include <bgfx/bgfx.h> #include "../../src/vertexdecl.h" #include <tinystl/allocator.h> -#include <tinystl/unordered_map.h> -#include <tinystl/unordered_set.h> #include <tinystl/string.h> +#include <tinystl/vector.h> namespace stl = tinystl; -#include <forsyth-too/forsythtriangleorderoptimizer.h> -#include <ib-compress/indexbuffercompression.h> +#include <meshoptimizer/src/meshoptimizer.h> #define BGFX_GEOMETRYC_VERSION_MAJOR 1 #define BGFX_GEOMETRYC_VERSION_MINOR 0 @@ -27,7 +22,7 @@ namespace stl = tinystl; #if 0 # define BX_TRACE(_format, ...) \ do { \ - printf(BX_FILE_LINE_LITERAL "BGFX " _format "\n", ##__VA_ARGS__); \ + bx::printf(BX_FILE_LINE_LITERAL "BGFX " _format "\n", ##__VA_ARGS__); \ } while(0) # define BX_WARN(_condition, _format, ...) \ @@ -59,32 +54,22 @@ namespace stl = tinystl; #include "bounds.h" -struct Vector3 -{ - float x; - float y; - float z; -}; - -typedef std::vector<Vector3> Vector3Array; +typedef stl::vector<bx::Vec3> Vec3Array; struct Index3 { int32_t m_position; int32_t m_texcoord; int32_t m_normal; - int32_t m_vertexIndex; int32_t m_vbc; // Barycentric ID. Holds eigher 0, 1 or 2. }; -typedef stl::unordered_map<uint64_t, Index3> Index3Map; - -struct Triangle +struct TriIndices { - uint64_t m_index[3]; + Index3 m_index[3]; }; -typedef std::vector<Triangle> TriangleArray; +typedef stl::vector<TriIndices> TriangleArray; struct Group { @@ -94,7 +79,7 @@ struct Group stl::string m_material; }; -typedef std::vector<Group> GroupArray; +typedef stl::vector<Group> GroupArray; struct Primitive { @@ -105,62 +90,67 @@ struct Primitive stl::string m_name; }; -typedef std::vector<Primitive> PrimitiveArray; +typedef stl::vector<Primitive> 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) +void optimizeVertexCache(uint16_t* _indices, uint32_t _numIndices, uint32_t _numVertices) { - long int pos = ftell(_file); - fseek(_file, 0L, SEEK_END); - long int size = ftell(_file); - fseek(_file, pos, SEEK_SET); - return size; + uint16_t* newIndexList = new uint16_t[_numIndices]; + meshopt_optimizeVertexCache(newIndexList, _indices, _numIndices, _numVertices); + bx::memCopy(_indices, newIndexList, _numIndices * 2); + delete[] newIndexList; } -void triangleReorder(uint16_t* _indices, uint32_t _numIndices, uint32_t _numVertices, uint16_t _cacheSize) +uint32_t optimizeVertexFetch(uint16_t* _indices, uint32_t _numIndices, uint8_t* _vertexData, uint32_t _numVertices, uint16_t _stride) { - uint16_t* newIndexList = new uint16_t[_numIndices]; - Forsyth::OptimizeFaces(_indices, _numIndices, _numVertices, 0, newIndexList, _cacheSize); - bx::memCopy(_indices, newIndexList, _numIndices*2); - delete [] newIndexList; + 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); + + return uint32_t(vertexCount); } -void triangleCompress(bx::WriterI* _writer, uint16_t* _indices, uint32_t _numIndices, uint8_t* _vertexData, uint32_t _numVertices, uint16_t _stride) +void writeCompressedIndices(bx::WriterI* _writer, const uint16_t* _indices, uint32_t _numIndices, uint32_t _numVertices) { - uint32_t* vertexRemap = (uint32_t*)malloc(_numVertices*sizeof(uint32_t) ); - - WriteBitstream writer; - CompressIndexBuffer(_indices, _numIndices/3, vertexRemap, _numVertices, IBCF_AUTO, writer); - writer.Finish(); - printf( "uncompressed: %10d, compressed: %10d, ratio: %0.2f%%\n" + size_t maxSize = meshopt_encodeIndexBufferBound(_numIndices, _numVertices); + unsigned char* compressedIndices = (unsigned char*)malloc(maxSize); + size_t compressedSize = meshopt_encodeIndexBuffer(compressedIndices, maxSize, _indices, _numIndices); + bx::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); + bx::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) +void calcTangents(void* _vertices, uint16_t _numVertices, bgfx::VertexLayout _layout, const uint16_t* _indices, uint32_t _numIndices) { struct PosTexcoord { @@ -188,14 +178,14 @@ void calcTangents(void* _vertices, uint16_t _numVertices, bgfx::VertexDecl _decl uint32_t i1 = indices[1]; uint32_t i2 = indices[2]; - bgfx::vertexUnpack(&v0.m_x, bgfx::Attrib::Position, _decl, _vertices, i0); - bgfx::vertexUnpack(&v0.m_u, bgfx::Attrib::TexCoord0, _decl, _vertices, i0); + bgfx::vertexUnpack(&v0.m_x, bgfx::Attrib::Position, _layout, _vertices, i0); + bgfx::vertexUnpack(&v0.m_u, bgfx::Attrib::TexCoord0, _layout, _vertices, i0); - bgfx::vertexUnpack(&v1.m_x, bgfx::Attrib::Position, _decl, _vertices, i1); - bgfx::vertexUnpack(&v1.m_u, bgfx::Attrib::TexCoord0, _decl, _vertices, i1); + bgfx::vertexUnpack(&v1.m_x, bgfx::Attrib::Position, _layout, _vertices, i1); + bgfx::vertexUnpack(&v1.m_u, bgfx::Attrib::TexCoord0, _layout, _vertices, i1); - bgfx::vertexUnpack(&v2.m_x, bgfx::Attrib::Position, _decl, _vertices, i2); - bgfx::vertexUnpack(&v2.m_u, bgfx::Attrib::TexCoord0, _decl, _vertices, i2); + bgfx::vertexUnpack(&v2.m_x, bgfx::Attrib::Position, _layout, _vertices, i2); + bgfx::vertexUnpack(&v2.m_u, bgfx::Attrib::TexCoord0, _layout, _vertices, i2); const float bax = v1.m_x - v0.m_x; const float bay = v1.m_y - v0.m_y; @@ -236,26 +226,22 @@ void calcTangents(void* _vertices, uint16_t _numVertices, bgfx::VertexDecl _decl for (uint32_t ii = 0; ii < _numVertices; ++ii) { - const float* tanu = &tangents[ii*6]; - const float* tanv = &tangents[ii*6 + 3]; - - float normal[4]; - bgfx::vertexUnpack(normal, bgfx::Attrib::Normal, _decl, _vertices, ii); - float ndt = bx::vec3Dot(normal, tanu); + const bx::Vec3 tanu = bx::load<bx::Vec3>(&tangents[ii*6]); + const bx::Vec3 tanv = bx::load<bx::Vec3>(&tangents[ii*6 + 3]); - float nxt[3]; - bx::vec3Cross(nxt, normal, tanu); + float nxyzw[4]; + bgfx::vertexUnpack(nxyzw, bgfx::Attrib::Normal, _layout, _vertices, ii); - float tmp[3]; - tmp[0] = tanu[0] - normal[0] * ndt; - tmp[1] = tanu[1] - normal[1] * ndt; - tmp[2] = tanu[2] - normal[2] * ndt; + const bx::Vec3 normal = bx::load<bx::Vec3>(nxyzw); + const float ndt = bx::dot(normal, tanu); + const bx::Vec3 nxt = bx::cross(normal, tanu); + const bx::Vec3 tmp = bx::sub(tanu, bx::mul(normal, ndt) ); float tangent[4]; - bx::vec3Norm(tangent, tmp); + bx::store(tangent, bx::normalize(tmp) ); + tangent[3] = bx::dot(nxt, tanv) < 0.0f ? -1.0f : 1.0f; - tangent[3] = bx::vec3Dot(nxt, tanv) < 0.0f ? -1.0f : 1.0f; - bgfx::vertexPack(tangent, true, bgfx::Attrib::Tangent, _decl, _vertices, ii); + bgfx::vertexPack(tangent, true, bgfx::Attrib::Tangent, _layout, _vertices, ii); } delete [] tangents; @@ -269,7 +255,7 @@ void write(bx::WriterI* _writer, const void* _vertices, uint32_t _numVertices, u Sphere minSphere; calcMinBoundingSphere(minSphere, _vertices, _numVertices, _stride); - if (minSphere.m_radius > maxSphere.m_radius) + if (minSphere.radius > maxSphere.radius) { bx::write(_writer, maxSphere); } @@ -290,11 +276,10 @@ void write(bx::WriterI* _writer, const void* _vertices, uint32_t _numVertices, u void write(bx::WriterI* _writer , const uint8_t* _vertices , uint32_t _numVertices - , const bgfx::VertexDecl& _decl + , const bgfx::VertexLayout& _layout , const uint16_t* _indices , uint32_t _numIndices - , const uint8_t* _compressedIndices - , uint32_t _compressedSize + , bool _compress , const stl::string& _material , const PrimitiveArray& _primitives ) @@ -302,21 +287,34 @@ void write(bx::WriterI* _writer using namespace bx; using namespace bgfx; - uint32_t stride = _decl.getStride(); - write(_writer, BGFX_CHUNK_MAGIC_VB); - write(_writer, _vertices, _numVertices, stride); + uint32_t stride = _layout.getStride(); + + if (_compress) + { + write(_writer, BGFX_CHUNK_MAGIC_VBC); + write(_writer, _vertices, _numVertices, stride); + + write(_writer, _layout); + + 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, _layout); - write(_writer, uint16_t(_numVertices) ); - write(_writer, _vertices, _numVertices*stride); + write(_writer, uint16_t(_numVertices) ); + write(_writer, _vertices, _numVertices*stride); + } - if (NULL != _compressedIndices) + if (_compress) { write(_writer, BGFX_CHUNK_MAGIC_IBC); write(_writer, _numIndices); - write(_writer, _compressedSize); - write(_writer, _compressedIndices, _compressedSize); + writeCompressedIndices(_writer, _indices, _numIndices, _numVertices); } else { @@ -365,20 +363,20 @@ void help(const char* _error = NULL) { if (NULL != _error) { - fprintf(stderr, "Error:\n%s\n\n", _error); + bx::printf("Error:\n%s\n\n", _error); } - fprintf(stderr - , "geometryc, bgfx geometry compiler tool, version %d.%d.%d.\n" - "Copyright 2011-2018 Branimir Karadzic. All rights reserved.\n" + bx::printf( + "geometryc, bgfx geometry compiler tool, version %d.%d.%d.\n" + "Copyright 2011-2019 Branimir Karadzic. All rights reserved.\n" "License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause\n\n" , BGFX_GEOMETRYC_VERSION_MAJOR , BGFX_GEOMETRYC_VERSION_MINOR , BGFX_API_VERSION ); - fprintf(stderr - , "Usage: geometryc -f <in> -o <out>\n" + bx::printf( + "Usage: geometryc -f <in> -o <out>\n" "\n" "Supported input file types:\n" @@ -417,8 +415,8 @@ int main(int _argc, const char* _argv[]) if (cmdLine.hasArg('v', "version") ) { - fprintf(stderr - , "geometryc, bgfx geometry compiler tool, version %d.%d.%d.\n" + bx::printf( + "geometryc, bgfx geometry compiler tool, version %d.%d.%d.\n" , BGFX_GEOMETRYC_VERSION_MAJOR , BGFX_GEOMETRYC_VERSION_MINOR , BGFX_API_VERSION @@ -472,28 +470,29 @@ int main(int _argc, const char* _argv[]) bool hasTangent = cmdLine.hasArg("tangent"); bool hasBc = cmdLine.hasArg("barycentric"); - FILE* file = fopen(filePath, "r"); - if (NULL == file) + bx::FileReader fr; + if (!bx::open(&fr, filePath) ) { - printf("Unable to open input file '%s'.", filePath); + bx::printf("Unable to open input file '%s'.", filePath); exit(bx::kExitFailure); } int64_t parseElapsed = -bx::getHPCounter(); int64_t triReorderElapsed = 0; - uint32_t size = (uint32_t)fsize(file); + uint32_t size = (uint32_t)bx::getSize(&fr); char* data = new char[size+1]; - size = (uint32_t)fread(data, 1, size, file); + size = bx::read(&fr, data, size); data[size] = '\0'; - fclose(file); + bx::close(&fr); - // https://en.wikipedia.org/wiki/Wavefront_.obj_file + // Reference(s): + // - Wavefront .obj file + // https://en.wikipedia.org/wiki/Wavefront_.obj_file - Vector3Array positions; - Vector3Array normals; - Vector3Array texcoords; - Index3Map indexMap; + Vec3Array positions; + Vec3Array normals; + Vec3Array texcoords; TriangleArray triangles; GroupArray groups; @@ -523,8 +522,8 @@ int main(int _argc, const char* _argv[]) } else if (0 == bx::strCmp(argv[0], "f") ) { - Triangle triangle; - bx::memSet(&triangle, 0, sizeof(Triangle) ); + TriIndices triangle; + bx::memSet(&triangle, 0, sizeof(TriIndices) ); const int numNormals = (int)normals.size(); const int numTexcoords = (int)texcoords.size(); @@ -534,14 +533,13 @@ int main(int _argc, const char* _argv[]) Index3 index; index.m_texcoord = -1; index.m_normal = -1; - index.m_vertexIndex = -1; if (hasBc) { index.m_vbc = edge < 3 ? edge : (1+(edge+1) )&1; } else { - index.m_vbc = 0; + index.m_vbc = 0; } { @@ -562,7 +560,9 @@ int main(int _argc, const char* _argv[]) texcoord.set(texcoord.getPtr() + 1, normal.getPtr()); - // https://en.wikipedia.org/wiki/Wavefront_.obj_file#Vertex_Normal_Indices_Without_Texture_Coordinate_Indices + // Reference(s): + // - Wavefront .obj file / Vertex normal indices without texture coordinate indices + // https://en.wikipedia.org/wiki/Wavefront_.obj_file#Vertex_Normal_Indices_Without_Texture_Coordinate_Indices if (!texcoord.isEmpty()) { int32_t tex; @@ -576,34 +576,15 @@ int main(int _argc, const char* _argv[]) index.m_position = (pos < 0) ? pos + numPositions : pos - 1; } - const uint64_t hash0 = uint64_t(index.m_position)<< 0; - const uint64_t hash1 = uint64_t(index.m_texcoord)<<20; - const uint64_t hash2 = uint64_t(index.m_normal )<<40; - const uint64_t hash3 = uint64_t(index.m_vbc )<<60; - const uint64_t hash = hash0^hash1^hash2^hash3; - - stl::pair<Index3Map::iterator, bool> result = indexMap.insert(stl::make_pair(hash, index) ); - if (!result.second) - { - Index3& oldIndex = result.first->second; - BX_UNUSED(oldIndex); - BX_CHECK(true - && oldIndex.m_position == index.m_position - && oldIndex.m_texcoord == index.m_texcoord - && oldIndex.m_normal == index.m_normal - , "Hash collision!" - ); - } - switch (edge) { case 0: case 1: case 2: - triangle.m_index[edge] = hash; + triangle.m_index[edge] = index; if (2 == edge) { if (ccw) { - std::swap(triangle.m_index[1], triangle.m_index[2]); + bx::swap(triangle.m_index[1], triangle.m_index[2]); } triangles.push_back(triangle); } @@ -613,12 +594,12 @@ int main(int _argc, const char* _argv[]) if (ccw) { triangle.m_index[2] = triangle.m_index[1]; - triangle.m_index[1] = hash; + triangle.m_index[1] = index; } else { triangle.m_index[1] = triangle.m_index[2]; - triangle.m_index[2] = hash; + triangle.m_index[2] = index; } triangles.push_back(triangle); @@ -642,7 +623,7 @@ int main(int _argc, const char* _argv[]) if (0 == bx::strCmp(argv[0], "vn") ) { - Vector3 normal; + bx::Vec3 normal; bx::fromString(&normal.x, argv[1]); bx::fromString(&normal.y, argv[2]); bx::fromString(&normal.z, argv[3]); @@ -655,12 +636,12 @@ int main(int _argc, const char* _argv[]) if (once) { once = false; - printf("warning: 'parameter space vertices' are unsupported.\n"); + bx::printf("warning: 'parameter space vertices' are unsupported.\n"); } } else if (0 == bx::strCmp(argv[0], "vt") ) { - Vector3 texcoord; + bx::Vec3 texcoord; texcoord.y = 0.0f; texcoord.z = 0.0f; @@ -689,7 +670,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]); } @@ -703,7 +684,7 @@ int main(int _argc, const char* _argv[]) py *= invW; pz *= invW; - Vector3 pos; + bx::Vec3 pos; pos.x = px; pos.y = py; pos.z = pz; @@ -763,55 +744,67 @@ int main(int _argc, const char* _argv[]) bool hasNormal; bool hasTexcoord; { - Index3Map::const_iterator it = indexMap.begin(); - hasNormal = -1 != it->second.m_normal; - hasTexcoord = -1 != it->second.m_texcoord; + TriangleArray::const_iterator it = triangles.begin(); + hasNormal = -1 != it->m_index[0].m_normal; + hasTexcoord = -1 != it->m_index[0].m_texcoord; if (!hasTexcoord) { - for (Index3Map::iterator jt = indexMap.begin(), jtEnd = indexMap.end(); jt != jtEnd && !hasTexcoord; ++jt) + for (TriangleArray::iterator jt = triangles.begin(), jtEnd = triangles.end(); jt != jtEnd && !hasTexcoord; ++jt) { - hasTexcoord |= -1 != jt->second.m_texcoord; + for (uint32_t i = 0; i < 3; ++i) + { + hasTexcoord |= -1 != jt->m_index[i].m_texcoord; + } } if (hasTexcoord) { - for (Index3Map::iterator jt = indexMap.begin(), jtEnd = indexMap.end(); jt != jtEnd; ++jt) + for (TriangleArray::iterator jt = triangles.begin(), jtEnd = triangles.end(); jt != jtEnd; ++jt) { - jt->second.m_texcoord = -1 == jt->second.m_texcoord ? 0 : jt->second.m_texcoord; + for (uint32_t i = 0; i < 3; ++i) + { + jt->m_index[i].m_texcoord = -1 == jt->m_index[i].m_texcoord ? 0 : jt->m_index[i].m_texcoord; + } } } } if (!hasNormal) { - for (Index3Map::iterator jt = indexMap.begin(), jtEnd = indexMap.end(); jt != jtEnd && !hasNormal; ++jt) + for (TriangleArray::iterator jt = triangles.begin(), jtEnd = triangles.end(); jt != jtEnd && !hasNormal; ++jt) { - hasNormal |= -1 != jt->second.m_normal; + for (uint32_t i = 0; i < 3; ++i) + { + hasNormal |= -1 != jt->m_index[i].m_normal; + } } if (hasNormal) { - for (Index3Map::iterator jt = indexMap.begin(), jtEnd = indexMap.end(); jt != jtEnd; ++jt) + for (TriangleArray::iterator jt = triangles.begin(), jtEnd = triangles.end(); jt != jtEnd; ++jt) { - jt->second.m_normal = -1 == jt->second.m_normal ? 0 : jt->second.m_normal; + for (uint32_t i = 0; i < 3; ++i) + { + jt->m_index[i].m_normal = -1 == jt->m_index[i].m_normal ? 0 : jt->m_index[i].m_normal; + } } } } } - bgfx::VertexDecl decl; - decl.begin(); - decl.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float); + bgfx::VertexLayout layout; + layout.begin(); + layout.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float); if (hasColor) { - decl.add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true); + layout.add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true); } if (hasBc) { - decl.add(bgfx::Attrib::Color1, 4, bgfx::AttribType::Uint8, true); + layout.add(bgfx::Attrib::Color1, 4, bgfx::AttribType::Uint8, true); } if (hasTexcoord) @@ -820,11 +813,11 @@ int main(int _argc, const char* _argv[]) { default: case 0: - decl.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float); + layout.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float); break; case 1: - decl.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Half); + layout.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Half); break; } } @@ -837,35 +830,43 @@ int main(int _argc, const char* _argv[]) { default: case 0: - decl.add(bgfx::Attrib::Normal, 3, bgfx::AttribType::Float); + layout.add(bgfx::Attrib::Normal, 3, bgfx::AttribType::Float); if (hasTangent) { - decl.add(bgfx::Attrib::Tangent, 4, bgfx::AttribType::Float); + layout.add(bgfx::Attrib::Tangent, 4, bgfx::AttribType::Float); } break; case 1: - decl.add(bgfx::Attrib::Normal, 4, bgfx::AttribType::Uint8, true, true); + layout.add(bgfx::Attrib::Normal, 4, bgfx::AttribType::Uint8, true, true); if (hasTangent) { - decl.add(bgfx::Attrib::Tangent, 4, bgfx::AttribType::Uint8, true, true); + layout.add(bgfx::Attrib::Tangent, 4, bgfx::AttribType::Uint8, true, true); } break; } } - decl.end(); + layout.end(); - uint32_t stride = decl.getStride(); + uint32_t stride = layout.getStride(); uint8_t* vertexData = new uint8_t[triangles.size() * 3 * stride]; 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; - + + const uint32_t tableSize = 65536 * 2; + const uint32_t hashmod = tableSize - 1; + uint32_t* table = new uint32_t[tableSize]; + bx::memSet(table, 0xff, tableSize * sizeof(uint32_t)); + stl::string material = groups.begin()->m_material; PrimitiveArray primitives; @@ -873,7 +874,7 @@ int main(int _argc, const char* _argv[]) bx::FileWriter writer; if (!bx::open(&writer, outFilePath) ) { - printf("Unable to open output file '%s'.", outFilePath); + bx::printf("Unable to open output file '%s'.", outFilePath); exit(bx::kExitFailure); } @@ -881,18 +882,22 @@ int main(int _argc, const char* _argv[]) prim.m_startVertex = 0; prim.m_startIndex = 0; - uint32_t positionOffset = decl.getOffset(bgfx::Attrib::Position); - uint32_t color0Offset = decl.getOffset(bgfx::Attrib::Color0); + uint32_t positionOffset = layout.getOffset(bgfx::Attrib::Position); + uint32_t color0Offset = layout.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; @@ -904,47 +909,36 @@ int main(int _argc, const char* _argv[]) if (hasTangent) { - calcTangents(vertexData, uint16_t(numVertices), decl, indexData, numIndices); + calcTangents(vertexData, uint16_t(numVertices), layout, 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 , vertexData , numVertices - , decl + , layout , indexData , numIndices - , (uint8_t*)memBlock.more() - , memBlock.getSize() + , compress , material , primitives ); primitives.clear(); + + bx::memSet(table, 0xff, tableSize * sizeof(uint32_t)); - for (Index3Map::iterator indexIt = indexMap.begin(); indexIt != indexMap.end(); ++indexIt) - { - indexIt->second.m_vertexIndex = -1; - } + ++writtenPrimitives; + writtenVertices += numVertices; + writtenIndices += numIndices; vertices = vertexData; indices = indexData; @@ -952,64 +946,91 @@ int main(int _argc, const char* _argv[]) numIndices = 0; prim.m_startVertex = 0; prim.m_startIndex = 0; - ++numPrimitives; material = groupIt->m_material; + + if (sentinel) + break; } - Triangle& triangle = triangles[tri]; + TriIndices& triangle = triangles[tri]; for (uint32_t edge = 0; edge < 3; ++edge) { - uint64_t hash = triangle.m_index[edge]; - Index3& index = indexMap[hash]; - if (index.m_vertexIndex == -1) + Index3& index = triangle.m_index[edge]; + + float* position = (float*)(vertices + positionOffset); + bx::memCopy(position, &positions[index.m_position], 3*sizeof(float) ); + + if (hasColor) { - index.m_vertexIndex = numVertices++; - - float* position = (float*)(vertices + positionOffset); - bx::memCopy(position, &positions[index.m_position], 3*sizeof(float) ); - - if (hasColor) + uint32_t* color0 = (uint32_t*)(vertices + color0Offset); + *color0 = rgbaToAbgr(numVertices%255, numIndices%255, 0, 0xff); + } + + if (hasBc) + { + const float bc[3] = { - uint32_t* color0 = (uint32_t*)(vertices + color0Offset); - *color0 = rgbaToAbgr(numVertices%255, numIndices%255, 0, 0xff); - } - - if (hasBc) + (index.m_vbc == 0) ? 1.0f : 0.0f, + (index.m_vbc == 1) ? 1.0f : 0.0f, + (index.m_vbc == 2) ? 1.0f : 0.0f, + }; + bgfx::vertexPack(bc, true, bgfx::Attrib::Color1, layout, vertices); + } + + if (hasTexcoord) + { + float uv[2]; + bx::memCopy(uv, &texcoords[index.m_texcoord], 2*sizeof(float) ); + + if (flipV) { - const float bc[3] = - { - (index.m_vbc == 0) ? 1.0f : 0.0f, - (index.m_vbc == 1) ? 1.0f : 0.0f, - (index.m_vbc == 2) ? 1.0f : 0.0f, - }; - bgfx::vertexPack(bc, true, bgfx::Attrib::Color1, decl, vertices); + uv[1] = -uv[1]; } + + bgfx::vertexPack(uv, true, bgfx::Attrib::TexCoord0, layout, vertices); + } + + if (hasNormal) + { + float normal[4]; + bx::store(normal, bx::normalize(bx::load<bx::Vec3>(&normals[index.m_normal]) ) ); + normal[3] = 0.0f; + bgfx::vertexPack(normal, true, bgfx::Attrib::Normal, layout, vertices); + } - if (hasTexcoord) + uint32_t hash = bx::hash<bx::HashMurmur2A>(vertices, stride); + size_t bucket = hash & hashmod; + uint32_t vertexIndex = UINT32_MAX; + + for (size_t probe = 0; probe <= hashmod; ++probe) + { + uint32_t& item = table[bucket]; + + if (item == ~0u) { - float uv[2]; - bx::memCopy(uv, &texcoords[index.m_texcoord], 2*sizeof(float) ); - - if (flipV) - { - uv[1] = -uv[1]; - } - - bgfx::vertexPack(uv, true, bgfx::Attrib::TexCoord0, decl, vertices); + vertices += stride; + item = numVertices++; + vertexIndex = item; + break; } - - if (hasNormal) + + if (0 == bx::memCmp(vertexData + item * stride, vertices, stride)) { - float normal[4]; - bx::vec3Norm(normal, (float*)&normals[index.m_normal]); - bgfx::vertexPack(normal, true, bgfx::Attrib::Normal, decl, vertices); + vertexIndex = item; + break; } - - vertices += stride; + + bucket = (bucket + probe + 1) & hashmod; } - - *indices++ = (uint16_t)index.m_vertexIndex; + + if ( vertexIndex == UINT32_MAX ) + { + bx::printf("hash table insert failed"); + exit(bx::kExitFailure); + } + + *indices++ = (uint16_t)vertexIndex; ++numIndices; } } @@ -1032,64 +1053,27 @@ 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::printf("size: %d\n", uint32_t(bx::seek(&writer) ) ); bx::close(&writer); + delete [] table; delete [] indexData; delete [] vertexData; now = bx::getHPCounter(); convertElapsed += now; - printf("parse %f [s]\ntri reorder %f [s]\nconvert %f [s]\n# %d, g %d, p %d, v %d, i %d\n" + bx::printf("parse %f [s]\ntri reorder %f [s]\nconvert %f [s]\n# %d, g %d, p %d, v %d, i %d\n" , double(parseElapsed)/bx::getHPFrequency() , double(triReorderElapsed)/bx::getHPFrequency() , double(convertElapsed)/bx::getHPFrequency() , num , uint32_t(groups.size() ) - , numPrimitives - , numVertices - , numIndices + , writtenPrimitives + , writtenVertices + , writtenIndices ); return bx::kExitSuccess; |