| 218 | } |
| 219 | |
| 220 | TrackStep* TrackDraw::Update(const Frame& pos, bool force) |
| 221 | { |
| 222 | if (!IS_SHADOW_VEHICLE) |
| 223 | { |
| 224 | return nullptr; |
| 225 | } |
| 226 | if (!_offsets) |
| 227 | { |
| 228 | return nullptr; |
| 229 | } |
| 230 | Point3 left = pos.PositionModelToWorld(_lOffset); |
| 231 | Point3 right = pos.PositionModelToWorld(_rOffset); |
| 232 | float eps = GLOB_ENGINE->ZShadowEpsilon(); |
| 233 | // RoadSurfaceY, not SurfaceY: roads float a few cm above the terrain mesh, |
| 234 | // so a terrain-height track sits below the road and is depth-rejected. |
| 235 | left[1] = GLOB_LAND->RoadSurfaceY(left[0], left[2]) + eps; |
| 236 | right[1] = GLOB_LAND->RoadSurfaceY(right[0], right[2]) + eps; |
| 237 | const float vMap = 2.0; |
| 238 | for (int level = 0; level < TrackLODLevels; level++) |
| 239 | { |
| 240 | const float levelCoef = 1 << level; |
| 241 | const float minStartTrackStep2 = Square(0.2 * levelCoef); |
| 242 | const float minFinishTrackStep2 = Square(1.0 * levelCoef); |
| 243 | const float maxFinishTrackStep2 = Square(4.0 * levelCoef); |
| 244 | const float maxFinishTrackTime = Square(0.25 * levelCoef); |
| 245 | TrackLODLevel& lod = _lods[level]; |
| 246 | if (!lod._initDone) |
| 247 | { |
| 248 | lod._lastL = left; |
| 249 | lod._lastR = right; |
| 250 | lod._initDone = true; |
| 251 | lod._lastV = fastFmod(lod._lastV, 1); |
| 252 | } |
| 253 | float distL2 = lod._lastL.Distance2(left); |
| 254 | float distR2 = lod._lastR.Distance2(right); |
| 255 | float maxDist2 = floatMax(distL2, distR2); |
| 256 | if (maxDist2 > 25 * 25) |
| 257 | { // too large step - skip it |
| 258 | lod._lastL = left; |
| 259 | lod._lastR = right; |
| 260 | } |
| 261 | if (!_lastPart) |
| 262 | { |
| 263 | if (maxDist2 > minStartTrackStep2 || maxDist2 > 1e-2 && force) |
| 264 | { |
| 265 | _lastPart = new TrackStep(_alpha, _texture); |
| 266 | _lastPart->SetPosition((lod._lastL + lod._lastR) * 0.5); |
| 267 | GLOB_LAND->AddObject(_lastPart); |
| 268 | // one ref in landscape, one in this |
| 269 | PoseidonAssert(_lastPart->RefCounter() == 2); |
| 270 | } |
| 271 | else |
| 272 | { |
| 273 | continue; |
| 274 | } |
| 275 | } |
| 276 | float v = lod._lastV + sqrt((distL2 + distR2) * 0.5) * vMap; |
| 277 | _lastPart->Change(level, lod._lastL, lod._lastR, lod._lastV, left, right, v); |
no test coverage detected