| 169 | ShadowCache::~ShadowCache() = default; |
| 170 | |
| 171 | Ref<Shape> ShadowCache::Shadow(Object* object, Vector3Par lightDir, int level, Matrix4Par pos, bool splitOnly) |
| 172 | { |
| 173 | int count = 0; |
| 174 | |
| 175 | RemmemberShadow* si = object->GetShadow(level); |
| 176 | |
| 177 | if (si) |
| 178 | { |
| 179 | const float maxLDDiff = 0.01f; |
| 180 | const float maxPosDiff = 0.02f; |
| 181 | // check |
| 182 | DoAssert(si->_splitOnly == splitOnly); |
| 183 | // check if the light or object position has not changed |
| 184 | if (!splitOnly && lightDir.Distance2(si->LightDir()) > Square(maxLDDiff) || |
| 185 | pos.Distance2(si->ObjectPos()) > Square(maxPosDiff)) |
| 186 | { |
| 187 | // both static and dynamic object shadows are cached |
| 188 | si->Init(object, lightDir, level, pos, splitOnly); |
| 189 | } |
| 190 | // reorder shadow cache |
| 191 | Ref<RemmemberShadow> temp = si; |
| 192 | _data.Delete(si); |
| 193 | _data.Insert(si); |
| 194 | si->_lastUsed = Glob.time; |
| 195 | } |
| 196 | else |
| 197 | { |
| 198 | // a new shadow |
| 199 | // _data is sorted by time when it was used |
| 200 | Ref<RemmemberShadow> entry; |
| 201 | int maxShadows = toLargeInt(Square(ENGINE_CONFIG.horizontZ) * (0.5 / 900)); |
| 202 | saturate(maxShadows, 512, 4096); |
| 203 | if (count >= maxShadows) |
| 204 | { |
| 205 | // remove last entry, mark as removed |
| 206 | entry = _data.Last(); |
| 207 | entry->GetObject()->RemoveShadow(entry->_level); |
| 208 | _data.Delete(entry); |
| 209 | } |
| 210 | else |
| 211 | { |
| 212 | entry = new RemmemberShadow; |
| 213 | } |
| 214 | entry->Init(object, lightDir, level, pos, splitOnly); |
| 215 | // create a new entry |
| 216 | _data.Insert(entry); |
| 217 | si = entry; |
| 218 | } |
| 219 | object->SetShadow(level, si); |
| 220 | |
| 221 | return si->_shadow; |
| 222 | } |
| 223 | |
| 224 | void ShadowCache::CleanUp() |
| 225 | { |
no test coverage detected