-
Notifications
You must be signed in to change notification settings - Fork 67
Smooth normal calculation Update! #941
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 11 commits
efa37a7
cc4a219
c018762
42ccf48
05ee8ed
f4b8ac6
0dd02e8
ce99287
28f73f5
5acb40d
0feb4e9
7424828
d078b2c
e72e0ef
e91aba1
509b359
a30ef6f
c580d72
5af4a9b
39e288c
c49d8d1
c688f7b
c521f95
a7aae4d
4a5c490
82f9820
401f1bb
9b007d2
7d31750
4699173
e65297b
dbffea5
ad0646e
60ec970
7ebd7d0
087beb8
6d4b794
0cdf7e8
4dbcbeb
ff42165
94c65b6
38ef627
bfba9fa
f3d9a19
f5d38f2
cc39901
1257d4d
d2503af
1386fba
ac2ed54
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,6 +9,7 @@ | |
|
|
||
| #include "nbl/asset/ICPUPolygonGeometry.h" | ||
| #include "nbl/asset/utils/CGeometryManipulator.h" | ||
| #include "nbl/asset/utils/CVertexHashGrid.h" | ||
|
|
||
| namespace nbl::asset | ||
| { | ||
|
|
@@ -17,15 +18,31 @@ namespace nbl::asset | |
| class NBL_API2 CPolygonGeometryManipulator | ||
| { | ||
| public: | ||
| //vertex data needed for CSmoothNormalGenerator | ||
| struct SSNGVertexData | ||
| { | ||
| uint32_t index; //offset of the vertex into index buffer | ||
| uint32_t hash; // | ||
| float wage; //angle wage of the vertex | ||
| hlsl::float32_t3 position; //position of the vertex in 3D space | ||
| hlsl::float32_t3 parentTriangleFaceNormal; // | ||
| }; | ||
|
|
||
| struct SSNGVertexData | ||
| { | ||
| uint64_t index; //offset of the vertex into index buffer | ||
devshgraphicsprogramming marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| uint32_t hash; | ||
| hlsl::float32_t3 weightedNormal; | ||
| // TODO(kevinyu): Should we separate this from SSNGVertexData, and store it in its own vector in VertexHashGrid? Similar like how hashmap work. Or keep it intrusive? | ||
devshgraphicsprogramming marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| hlsl::float32_t3 position; //position of the vertex in 3D space | ||
|
||
|
|
||
| hlsl::float32_t3 getPosition() const | ||
| { | ||
| return position; | ||
| } | ||
|
|
||
| void setHash(uint32_t hash) | ||
| { | ||
| this->hash = hash; | ||
| } | ||
|
|
||
| uint32_t getHash() const | ||
| { | ||
| return hash; | ||
| }; | ||
|
|
||
| }; | ||
|
|
||
| using VxCmpFunction = std::function<bool(const SSNGVertexData&, const SSNGVertexData&, const ICPUPolygonGeometry*)>; | ||
|
|
||
|
|
@@ -247,7 +264,7 @@ class NBL_API2 CPolygonGeometryManipulator | |
| VxCmpFunction vxcmp = [](const CPolygonGeometryManipulator::SSNGVertexData& v0, const CPolygonGeometryManipulator::SSNGVertexData& v1, const ICPUPolygonGeometry* buffer) | ||
| { | ||
| static constexpr float cosOf45Deg = 0.70710678118f; | ||
devshgraphicsprogramming marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return dot(v0.parentTriangleFaceNormal,v1.parentTriangleFaceNormal) > cosOf45Deg; | ||
| return dot(normalize(v0.weightedNormal),normalize(v1.weightedNormal)) > cosOf45Deg; | ||
| }); | ||
|
|
||
| #if 0 // TODO: REDO | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,212 @@ | ||
| #ifndef _NBL_ASSET_C_VERTEX_HASH_MAP_H_INCLUDED_ | ||
| #define _NBL_ASSET_C_VERTEX_HASH_MAP_H_INCLUDED_ | ||
|
|
||
| #include "nbl/core/declarations.h" | ||
|
|
||
| namespace nbl::asset | ||
| { | ||
|
|
||
| template <typename T> | ||
| concept HashGridVertexData = requires(T obj, T const cobj, uint32_t hash) { | ||
| { cobj.getHash() } -> std::same_as<uint32_t>; | ||
| { obj.setHash(hash) } -> std::same_as<void>; | ||
| { cobj.getPosition() } -> std::same_as<hlsl::float32_t3>; | ||
| }; | ||
devshgraphicsprogramming marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| template <HashGridVertexData VertexData> | ||
| class CVertexHashGrid | ||
| { | ||
| public: | ||
|
|
||
| using vertex_data_t = VertexData; | ||
| using collection_t = core::vector<VertexData>; | ||
| struct BucketBounds | ||
| { | ||
| collection_t::const_iterator begin; | ||
| collection_t::const_iterator end; | ||
| }; | ||
|
|
||
| CVertexHashGrid(size_t _vertexCount, uint32_t _hashTableMaxSize, float _cellSize) : | ||
devshgraphicsprogramming marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| m_sorter(createSorter(_vertexCount)), | ||
| m_hashTableMaxSize(_hashTableMaxSize), | ||
| m_cellSize(_cellSize) | ||
| { | ||
| assert((core::isPoT(m_hashTableMaxSize))); | ||
devshgraphicsprogramming marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| m_vertices.reserve(_vertexCount); | ||
| } | ||
|
|
||
| //inserts vertex into hash table | ||
| void add(VertexData&& vertex) | ||
| { | ||
| vertex.setHash(hash(vertex)); | ||
| m_vertices.push_back(vertex); | ||
devshgraphicsprogramming marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| void validate() | ||
devshgraphicsprogramming marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| { | ||
| const auto oldSize = m_vertices.size(); | ||
| m_vertices.resize(oldSize*2u); | ||
| auto finalSortedOutput = std::visit( [&](auto& sorter) { return sorter(m_vertices.data(), m_vertices.data() + oldSize, oldSize, KeyAccessor()); },m_sorter ); | ||
|
|
||
| if (finalSortedOutput != m_vertices.data()) | ||
| m_vertices.erase(m_vertices.begin(), m_vertices.begin() + oldSize); | ||
| else | ||
| m_vertices.resize(oldSize); | ||
devshgraphicsprogramming marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| const collection_t& vertices() const { return m_vertices; } | ||
|
|
||
| collection_t& vertices(){ return m_vertices; } | ||
devshgraphicsprogramming marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| inline uint32_t getVertexCount() const { return m_vertices.size(); } | ||
|
|
||
| template <typename Fn> | ||
| void iterateBroadphaseCandidates(const VertexData& vertex, Fn fn) const | ||
devshgraphicsprogramming marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| { | ||
| std::array<uint32_t, 8> neighboringCells; | ||
| const auto cellCount = getNeighboringCellHashes(neighboringCells.data(), vertex); | ||
|
|
||
| //iterate among all neighboring cells | ||
| for (uint8_t i = 0; i < cellCount; i++) | ||
| { | ||
| const auto& neighborCell = neighboringCells[i]; | ||
| BucketBounds bounds = getBucketBoundsByHash(neighborCell); | ||
| for (; bounds.begin != bounds.end; bounds.begin++) | ||
| { | ||
| const vertex_data_t& neighborVertex = *bounds.begin; | ||
| if (&vertex != &neighborVertex) | ||
|
||
| if (!fn(neighborVertex)) break; | ||
devshgraphicsprogramming marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
| } | ||
|
|
||
| }; | ||
|
|
||
| private: | ||
| struct KeyAccessor | ||
| { | ||
| _NBL_STATIC_INLINE_CONSTEXPR size_t key_bit_count = 32ull; | ||
devshgraphicsprogramming marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| template<auto bit_offset, auto radix_mask> | ||
| inline decltype(radix_mask) operator()(const VertexData& item) const | ||
| { | ||
| return static_cast<decltype(radix_mask)>(item.getHash() >> static_cast<uint32_t>(bit_offset)) & radix_mask; | ||
| } | ||
| }; | ||
|
|
||
| static constexpr uint32_t primeNumber1 = 73856093; | ||
| static constexpr uint32_t primeNumber2 = 19349663; | ||
| static constexpr uint32_t primeNumber3 = 83492791; | ||
devshgraphicsprogramming marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| static constexpr uint32_t invalidHash = 0xFFFFFFFF; | ||
|
|
||
| using sorter_t = std::variant< | ||
| core::LSBSorter<KeyAccessor::key_bit_count, uint16_t>, | ||
| core::LSBSorter<KeyAccessor::key_bit_count, uint32_t>, | ||
| core::LSBSorter<KeyAccessor::key_bit_count, size_t>>; | ||
| sorter_t m_sorter; | ||
|
|
||
| static sorter_t createSorter(size_t vertexCount) | ||
| { | ||
| if (vertexCount < (0x1ull << 16ull)) | ||
| return core::LSBSorter<KeyAccessor::key_bit_count, uint16_t>(); | ||
| if (vertexCount < (0x1ull << 32ull)) | ||
| return core::LSBSorter<KeyAccessor::key_bit_count, uint32_t>(); | ||
| return core::LSBSorter<KeyAccessor::key_bit_count, size_t>(); | ||
| } | ||
|
|
||
| collection_t m_vertices; | ||
| const uint32_t m_hashTableMaxSize; | ||
| const float m_cellSize; | ||
|
|
||
| uint32_t hash(const VertexData& vertex) const | ||
| { | ||
| const hlsl::float32_t3 position = floor(vertex.getPosition() / m_cellSize); | ||
|
|
||
| return ((static_cast<uint32_t>(position.x) * primeNumber1) ^ | ||
| (static_cast<uint32_t>(position.y) * primeNumber2) ^ | ||
| (static_cast<uint32_t>(position.z) * primeNumber3))& (m_hashTableMaxSize - 1); | ||
| } | ||
|
|
||
| uint32_t hash(const hlsl::uint32_t3& position) const | ||
| { | ||
| return ((position.x * primeNumber1) ^ | ||
| (position.y * primeNumber2) ^ | ||
| (position.z * primeNumber3))& (m_hashTableMaxSize - 1); | ||
| } | ||
devshgraphicsprogramming marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| uint8_t getNeighboringCellHashes(uint32_t* outNeighbors, const VertexData& vertex) const | ||
| { | ||
| hlsl::float32_t3 cellfloatcoord = floor(vertex.getPosition() / m_cellSize - hlsl::float32_t3(0.5)); | ||
| hlsl::uint32_t3 baseCoord = hlsl::uint32_t3(static_cast<uint32_t>(cellfloatcoord.x), static_cast<uint32_t>(cellfloatcoord.y), static_cast<uint32_t>(cellfloatcoord.z)); | ||
devshgraphicsprogramming marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| uint8_t neighborCount = 0; | ||
|
|
||
| outNeighbors[neighborCount] = hash(baseCoord); | ||
| neighborCount++; | ||
|
|
||
| auto addUniqueNeighbor = [&neighborCount, outNeighbors](uint32_t hashval) | ||
| { | ||
| if (std::find(outNeighbors, outNeighbors + neighborCount, hashval) == outNeighbors + neighborCount) | ||
| { | ||
| outNeighbors[neighborCount] = hashval; | ||
| neighborCount++; | ||
| } | ||
| }; | ||
|
|
||
| addUniqueNeighbor(hash(baseCoord + hlsl::uint32_t3(0, 0, 1))); | ||
| addUniqueNeighbor(hash(baseCoord + hlsl::uint32_t3(0, 1, 0))); | ||
| addUniqueNeighbor(hash(baseCoord + hlsl::uint32_t3(1, 0, 0))); | ||
| addUniqueNeighbor(hash(baseCoord + hlsl::uint32_t3(1, 1, 0))); | ||
| addUniqueNeighbor(hash(baseCoord + hlsl::uint32_t3(1, 0, 1))); | ||
| addUniqueNeighbor(hash(baseCoord + hlsl::uint32_t3(0, 1, 1))); | ||
| addUniqueNeighbor(hash(baseCoord + hlsl::uint32_t3(1, 1, 1))); | ||
|
|
||
| return neighborCount; | ||
| } | ||
|
|
||
| BucketBounds getBucketBoundsByHash(uint32_t hash) const | ||
| { | ||
| if (hash == invalidHash) | ||
| return { m_vertices.end(), m_vertices.end() }; | ||
devshgraphicsprogramming marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| const auto skipListBound = std::visit([&](auto& sorter) | ||
| { | ||
| auto hashBound = sorter.getHashBound(hash); | ||
| return std::pair<collection_t::const_iterator, collection_t::const_iterator>(m_vertices.begin() + hashBound.first, m_vertices.begin() + hashBound.second); | ||
| }, m_sorter); | ||
|
|
||
| auto begin = std::lower_bound( | ||
| skipListBound.first, | ||
| skipListBound.second, | ||
| hash, | ||
| [](const VertexData& vertex, uint32_t hash) | ||
| { | ||
| return vertex.hash < hash; | ||
| }); | ||
|
|
||
| auto end = std::upper_bound( | ||
| skipListBound.first, | ||
| skipListBound.second, | ||
| hash, | ||
| [](uint32_t hash, const VertexData& vertex) | ||
| { | ||
| return hash < vertex.hash; | ||
devshgraphicsprogramming marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| }); | ||
|
|
||
| const auto beginIx = begin - m_vertices.begin(); | ||
| const auto endIx = end - m_vertices.begin(); | ||
| //bucket missing | ||
| if (begin == end) | ||
| return { m_vertices.end(), m_vertices.end() }; | ||
|
|
||
| //bucket missing | ||
| if (begin->hash != hash) | ||
| return { m_vertices.end(), m_vertices.end() }; | ||
|
|
||
| return { begin, end }; | ||
| } | ||
| }; | ||
|
|
||
| } | ||
| #endif | ||
Uh oh!
There was an error while loading. Please reload this page.