Panda3D
shadowAtlas.I
1 /**
2  *
3  * RenderPipeline
4  *
5  * Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  *
25  */
26 
27 
28 /**
29  * @brief Returns the tile size of the atlas.
30  * @details This returns the tile size of the atlas, which was set in the
31  * constructor. This is the smalles unit of the atlas, and every resolution
32  * has to be a multiple of the tile size.
33  * @return Tile size in pixels
34  */
35 inline int ShadowAtlas::get_tile_size() const {
36  return _tile_size;
37 }
38 
39 /**
40  * @brief Sets a specific tile status.
41  * @details This marks a tile to either reserved or free, depending on the flag.
42  * If flag is true, the tile gets marked as reserved. If flag is false, the
43  * tile gets marked as free.
44  *
45  * No bounds checking is done for performance reasons. Passing an invalid tile
46  * index causes a crash. The coordinates are expected to be in tile space.
47  *
48  * @param x x-position of the tile
49  * @param y y-position of the tile
50  * @param flag Flag to set the tile to
51  */
52 inline void ShadowAtlas::set_tile(size_t x, size_t y, bool flag) {
53  _flags[x + y * _num_tiles] = flag;
54 }
55 
56 /**
57  * @brief Returns the status of a given tile.
58  * @details This returns the value of a tile. If the tile is true, this means
59  * the tile is already reserved. If the tile is false, the tile can be
60  * used, and is not reserved.
61  *
62  * No bounds checking is done for performance reasons. Passing an invalid tile
63  * index causes a crash. The coordinates are expected to be in tile space.
64  *
65  * @param x x-position of the tile
66  * @param y y-position of the tile
67  *
68  * @return Tile-Status
69  */
70 inline bool ShadowAtlas::get_tile(size_t x, size_t y) const {
71  return _flags[x + y * _num_tiles];
72 }
73 
74 /**
75  * @brief Checks wheter a given region is free.
76  * @details This checks whether a given region in the atlas is still free. This
77  * is true if *all* tiles in that region are false, and thus are not taken yet.
78  * The coordinates are expected to be in tile space.
79  *
80  * Passing an invalid region, causes an assertion, in case those are enabled.
81  * If assertions are optimized out, this method will crash when passing invalid
82  * bounds.
83  *
84  * @param x x- start position of the region
85  * @param y y- start position of the region
86  * @param w width of the region
87  * @param h height of the region
88  * @return true if the region is completely free, else false
89  */
90 inline bool ShadowAtlas::region_is_free(size_t x, size_t y, size_t w, size_t h) const {
91  // Check if we are out of bounds, this should be disabled for performance
92  // reasons at some point.
93  nassertr(x >= 0 && y >= 0 && x + w <= _num_tiles && y + h <= _num_tiles, false);
94 
95  // Iterate over every tile in that region and check if it is still free.
96  for (size_t cx = 0; cx < w; ++cx) {
97  for (size_t cy = 0; cy < h; ++cy) {
98  if (get_tile(cx + x, cy + y)) return false;
99  }
100  }
101  return true;
102 }
103 
104 /**
105  * @brief Returns the amount of tiles required to store a resolution.
106  * @details Returns the amount of tiles which would be required to store a
107  * given resolution. This basically just returns resolution / tile_size.
108  *
109  * When an invalid resolution is passed (not a multiple of the tile size),
110  * an error is printed and 1 is returned.
111  * When a negative or zero resolution is passed, undefined behaviour occurs.
112  *
113  * @param resolution The resolution to compute the amount of tiles for
114  * @return Amount of tiles to store the resolution
115  */
116 inline int ShadowAtlas::get_required_tiles(size_t resolution) const {
117  nassertr(resolution > 0, -1);
118 
119  if (resolution % _tile_size != 0) {
120  shadowatlas_cat.error() << "Resolution " << resolution << " is not a multiple "
121  << "of the shadow atlas tile size (" << _tile_size << ")!" << std::endl;
122  return 1;
123  }
124  return resolution / _tile_size;
125 }
126 
127 /**
128  * @brief Converts a tile-space region to uv space.
129  * @details This converts a region (presumably from ShadowAtlas::find_and_reserve_region)
130  * to uv space (0 .. 1 range). This can be used in shaders, since they expect
131  * floating point coordinates instead of integer coordinates.
132  *
133  * @param region tile-space region
134  * @return uv-space region
135  */
136 inline LVecBase4 ShadowAtlas::region_to_uv(const LVecBase4i& region) {
137  LVecBase4 flt = LVecBase4(region.get_x(), region.get_y(), region.get_z(), region.get_w());
138  return flt * ((float)_tile_size / (float)_size);
139 }
140 
141 /**
142  * @brief Returns the amount of used tiles
143  * @details Returns the amount of used tiles in the atlas
144  * @return Amount of used tiles
145  */
146 inline int ShadowAtlas::get_num_used_tiles() const {
147  return _num_used_tiles;
148 }
149 
150 /**
151  * @brief Returns the amount of used tiles in percentage
152  * @details This returns in percentage from 0 to 1 how much space of the atlas
153  * is used right now. A value of 1 means the atlas is completely full, whereas
154  * a value of 0 means the atlas is completely free.
155  * @return Atlas usage in percentage
156  */
157 inline float ShadowAtlas::get_coverage() const {
158  return float(_num_used_tiles) / float(_num_tiles * _num_tiles);
159 }
int get_tile_size() const
RenderPipeline.
Definition: shadowAtlas.I:35
int get_required_tiles(size_t resolution) const
Returns the amount of tiles required to store a resolution.
Definition: shadowAtlas.I:116
LVecBase4 region_to_uv(const LVecBase4i &region)
Converts a tile-space region to uv space.
Definition: shadowAtlas.I:136
get_coverage
Returns the amount of used tiles in percentage.
Definition: shadowAtlas.h:50