From 35a39f6c009f9a307aa8393d933cabb44ec3f9a9 Mon Sep 17 00:00:00 2001 From: bkaradzic Date: Sat, 2 Nov 2013 23:00:31 -0700 Subject: [PATCH] Added vertex welding support. --- include/bgfx.h | 12 +++++++++++ src/vertexdecl.cpp | 52 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/include/bgfx.h b/include/bgfx.h index 19ca3627..d01f10aa 100644 --- a/include/bgfx.h +++ b/include/bgfx.h @@ -562,6 +562,18 @@ namespace bgfx /// void vertexConvert(const VertexDecl& _destDecl, void* _destData, const VertexDecl& _srcDecl, const void* _srcData, uint32_t _num = 1); + /// Weld vertices. + /// + /// @param _output Welded vertices remapping table. The size of buffer + /// must be the same as number of vertices. + /// @param _decl Vertex stream declaration. + /// @param _data Vertex stream. + /// @param _num Number of vertices in vertex stream. + /// @param _epsilon Error tolerance for vertex position comparison. + /// @returns Number of unique vertices after vertex welding. + /// + uint16_t weldVertices(uint16_t* _output, const VertexDecl& _decl, const void* _data, uint16_t _num, float _epsilon = 0.001f); + /// Swizzle RGBA8 image to BGRA8. /// /// @param _width Width of input image (pixels). diff --git a/src/vertexdecl.cpp b/src/vertexdecl.cpp index 8513629f..366d1a60 100644 --- a/src/vertexdecl.cpp +++ b/src/vertexdecl.cpp @@ -483,4 +483,56 @@ namespace bgfx } } + inline float sqLength(const float _a[3], const float _b[3]) + { + const float xx = _a[0] - _b[0]; + const float yy = _a[1] - _b[1]; + const float zz = _a[2] - _b[2]; + return xx*xx + yy*yy + zz*zz; + } + + uint16_t weldVertices(uint16_t* _output, const VertexDecl& _decl, const void* _data, uint16_t _num, float _epsilon) + { + const uint32_t hashSize = bx::uint32_nextpow2(_num); + const uint32_t hashMask = hashSize-1; + const float epsilonSq = _epsilon*_epsilon; + + uint32_t numVertices = 0; + + const uint32_t size = sizeof(uint16_t)*(hashSize + _num); + uint16_t* hashTable = (uint16_t*)alloca(size); + memset(hashTable, 0xff, size); + + uint16_t* next = hashTable + hashSize; + + for (uint32_t ii = 0; ii < _num; ++ii) + { + float pos[4]; + vertexUnpack(pos, bgfx::Attrib::Position, _decl, _data, ii); + uint32_t hashValue = bx::hashMurmur2A(pos, 3*sizeof(float) ) & hashMask; + + uint16_t offset = hashTable[hashValue]; + for (; UINT16_MAX != offset; offset = next[offset]) + { + float test[4]; + vertexUnpack(test, bgfx::Attrib::Position, _decl, _data, _output[offset]); + if (sqLength(test, pos) < epsilonSq) + { + _output[ii] = _output[offset]; + break; + } + } + + if (UINT16_MAX == offset) + { + _output[ii] = ii; + next[numVertices] = hashTable[hashValue]; + hashTable[hashValue] = ii; + numVertices++; + } + } + + return numVertices; + } + } // namespace bgfx