Polyphase Game Engine
Loading...
Searching...
No Matches
OcclusionData.h
Go to the documentation of this file.
1#pragma once
2
3#include "PolyphaseAPI.h"
4#include "Maths.h"
5#include "EngineTypes.h"
6
7#include <vector>
8#include <unordered_map>
9#include <stdint.h>
10
11class Stream;
12
13// World-space AABB of an occluder / occludee at bake time. Used to match
14// baked entries back to live nodes when a scene is instantiated.
16{
17 glm::vec3 mCenter = {};
18 glm::vec3 mExtents = {};
19};
20
21// Baked potentially-visible-set for one Scene. The bake volume is split into
22// uniform cells; each cell maps to a bitset of occludees that can be seen
23// from anywhere inside that cell. Identical bitsets are shared through
24// mSetPool so the table stays small on consoles.
25//
26// Optionally a second, coarser table records which coarse cells (blocks of
27// mCoarseFactor^3 cells) are visible from each cell. Moving objects that are
28// flagged as occludees are tested against that table by their current bounds.
30{
31public:
32
33 static constexpr uint32_t kNoSet = 0xFFFFFFFFu; // constexpr: ODR-used (vector::assign takes a reference)
34
35 bool IsValid() const;
36 bool HasDynamicTable() const;
37 void Clear();
38
39 int32_t FindCell(glm::vec3 point) const;
40 uint32_t GetCellSetIndex(int32_t cell) const;
41 const uint32_t* GetSet(int32_t cell) const;
42 bool IsVisible(const uint32_t* set, uint32_t occludeeIndex) const;
43
44 // Dynamic (coarse) table.
45 const uint32_t* GetCoarseSet(int32_t cell) const;
46 bool IsCoarseCellVisible(const uint32_t* coarseSet, uint32_t coarseIndex) const;
47 uint32_t GetNumCoarseCells() const { return mCoarseDimX * mCoarseDimY * mCoarseDimZ; }
48 uint32_t GetNumUniqueCoarseSets() const { return mWordsPerCoarseSet > 0 ? uint32_t(mCoarseSetPool.size() / mWordsPerCoarseSet) : 0; }
49 // True if any coarse cell overlapped by the box is visible from `cell`.
50 // Boxes that leave the volume or cover more than kMaxDynamicCoarseCells
51 // are reported visible.
52 bool IsBoxVisibleDynamic(int32_t cell, const AABB& box) const;
53
54 uint32_t GetNumCells() const { return mDimX * mDimY * mDimZ; }
55 uint32_t GetNumUniqueSets() const { return mWordsPerSet > 0 ? uint32_t(mSetPool.size() / mWordsPerSet) : 0; }
56 AABB GetCellAABB(int32_t cell) const;
57 AABB GetVolumeAABB() const;
58 size_t GetMemoryBytes() const;
59 size_t GetStaticTableBytes() const;
60 size_t GetDynamicTableBytes() const;
61
62 // Cell -> set index storage. Uses 16-bit indices when the pool is small
63 // enough (the common case), which halves the biggest table on consoles.
64 void SetCellSetIndices(const std::vector<uint32_t>& cellToSet);
65 void SetCellCoarseSetIndices(const std::vector<uint32_t>& cellToSet);
66
67 void SaveStream(Stream& stream) const;
68 void LoadStream(Stream& stream, uint32_t version);
69
70 static const uint32_t kMaxDynamicCoarseCells = 64;
71
72 glm::vec3 mMin = {};
73 float mCellSize = 4.0f;
74 uint32_t mDimX = 0;
75 uint32_t mDimY = 0;
76 uint32_t mDimZ = 0;
77 uint32_t mWordsPerSet = 0;
78 // Sampling scheme that produced this data. The baker only reuses bits
79 // from a previous bake made with the same scheme.
80 uint32_t mBakeAlgorithm = 0;
81
82 std::vector<OcclusionEntry> mOccludees;
83 std::vector<OcclusionEntry> mOccluders;
84 std::vector<uint16_t> mCellToSet16; // used when every index fits (0xFFFF = kNoSet)
85 std::vector<uint32_t> mCellToSet32; // otherwise
86 std::vector<uint32_t> mSetPool;
87
88 // Dynamic table (0 factor = not baked).
89 uint32_t mCoarseFactor = 0;
90 uint32_t mCoarseDimX = 0;
91 uint32_t mCoarseDimY = 0;
92 uint32_t mCoarseDimZ = 0;
93 uint32_t mWordsPerCoarseSet = 0;
94 std::vector<uint16_t> mCellToCoarseSet16;
95 std::vector<uint32_t> mCellToCoarseSet32;
96 std::vector<uint32_t> mCoarseSetPool;
97
98private:
99
100 uint32_t GetCoarseSetIndex(int32_t cell) const;
101};
102
103// Tolerant lookup of OcclusionEntry records by world-space AABB. Entries are
104// bucketed by position; a query matches the closest entry whose center and
105// extents are within 10% of a cell or 1% of the object's size. Cloned (PIE)
106// and re-instantiated trees rebuild rotations from euler properties and the
107// float noise on a large rotated wall exceeds any exact quantisation.
109{
110public:
111
112 void Build(const std::vector<OcclusionEntry>& entries, float cellSize);
113 int32_t Find(glm::vec3 center, glm::vec3 extents) const;
114
115private:
116
117 uint64_t Key(glm::vec3 p) const;
118
119 const std::vector<OcclusionEntry>* mEntries = nullptr;
120 float mCellSize = 1.0f;
121 float mBucketSize = 1.0f;
122 std::unordered_map<uint64_t, std::vector<uint32_t>> mBuckets;
123};
Export macros for Polyphase Engine symbols.
#define POLYPHASE_API
Definition PolyphaseAPI.h:31
Definition OcclusionData.h:30
std::vector< uint32_t > mCellToSet32
Definition OcclusionData.h:85
uint32_t GetNumCoarseCells() const
Definition OcclusionData.h:47
std::vector< uint32_t > mSetPool
Definition OcclusionData.h:86
std::vector< uint16_t > mCellToSet16
Definition OcclusionData.h:84
std::vector< OcclusionEntry > mOccluders
Definition OcclusionData.h:83
uint32_t GetNumCells() const
Definition OcclusionData.h:54
std::vector< uint32_t > mCoarseSetPool
Definition OcclusionData.h:96
uint32_t GetNumUniqueSets() const
Definition OcclusionData.h:55
std::vector< OcclusionEntry > mOccludees
Definition OcclusionData.h:82
std::vector< uint32_t > mCellToCoarseSet32
Definition OcclusionData.h:95
uint32_t GetNumUniqueCoarseSets() const
Definition OcclusionData.h:48
std::vector< uint16_t > mCellToCoarseSet16
Definition OcclusionData.h:94
Definition OcclusionData.h:109
Definition Stream.h:21
Definition EngineTypes.h:213
Definition OcclusionData.h:16
glm::vec3 mCenter
Definition OcclusionData.h:17
glm::vec3 mExtents
Definition OcclusionData.h:18