| 315 | #endif |
| 316 | |
| 317 | void DetailObjectSurface::PreDrawCamera(const mat4& transform) { |
| 318 | if (g_debug_runtime_disable_detail_object_surface_pre_draw) { |
| 319 | return; |
| 320 | } |
| 321 | |
| 322 | draw_detail_instances.clear(); |
| 323 | draw_detail_instance_transforms.clear(); |
| 324 | |
| 325 | Camera* cam = ActiveCameras::Get(); |
| 326 | float temp_view_dist = view_dist * min(3.0f, 90.0f / cam->GetFOV()); |
| 327 | const int _tile_radius = (int)ceilf((temp_view_dist) / _tile_size); // How many tiles are visible in each direction |
| 328 | vec3 cam_pos = cam->GetPos(); |
| 329 | |
| 330 | TriInt cam_ti = GetTriInt(cam_pos); |
| 331 | TriInt test_ti(0, 0, 0); |
| 332 | |
| 333 | const Model& model = Models::Instance()->GetModel(detail_model_id); |
| 334 | float cull_dist_squared = square(temp_view_dist + model.bounding_sphere_radius); |
| 335 | |
| 336 | if (Graphics::Instance()->config_.detail_objects()) { |
| 337 | PROFILER_ZONE(g_profiler_ctx, "Calculate visible detail instances"); |
| 338 | |
| 339 | int bounds[6]; |
| 340 | bounds[0] = max(bounding_box[0], cam_ti.val[0] - _tile_radius); |
| 341 | bounds[1] = min(bounding_box[1], cam_ti.val[0] + _tile_radius); |
| 342 | bounds[2] = max(bounding_box[2], cam_ti.val[1] - _tile_radius); |
| 343 | bounds[3] = min(bounding_box[3], cam_ti.val[1] + _tile_radius); |
| 344 | bounds[4] = max(bounding_box[4], cam_ti.val[2] - _tile_radius); |
| 345 | bounds[5] = min(bounding_box[5], cam_ti.val[2] + _tile_radius); |
| 346 | |
| 347 | const vec4 modelBoundingSphereOrigin = vec4(model.bounding_sphere_origin); |
| 348 | |
| 349 | PatchesMap::iterator iter; |
| 350 | for (int i = bounds[0]; i <= bounds[1]; ++i) { |
| 351 | for (int j = bounds[2]; j <= bounds[3]; ++j) { |
| 352 | for (int k = bounds[4]; k <= bounds[5]; ++k) { |
| 353 | test_ti.val[0] = i; |
| 354 | test_ti.val[1] = j; |
| 355 | test_ti.val[2] = k; |
| 356 | iter = patches.find(test_ti); |
| 357 | if (iter != patches.end()) { |
| 358 | if (!iter->second.calculated || g_detail_objects_reduced_dirty) { |
| 359 | CalcPatchInstances(iter->first, iter->second, transform); |
| 360 | } |
| 361 | DOPatch& patch = iter->second; |
| 362 | if (!patch.detail_instances.empty()) { |
| 363 | float square_patch_dist = distance_squared(patch.sphere_center, cam_pos); |
| 364 | if (square_patch_dist < square(temp_view_dist + patch.sphere_radius)) { |
| 365 | int in_frustum = cam->checkSphereInFrustum(patch.sphere_center, patch.sphere_radius); |
| 366 | if (in_frustum == 2 && square_patch_dist > square(temp_view_dist - patch.sphere_radius)) { |
| 367 | in_frustum = 1; |
| 368 | } |
| 369 | if (in_frustum == 1) { |
| 370 | static std::vector<uint32_t> is_visible; |
| 371 | is_visible.clear(); |
| 372 | is_visible.resize(patch.detail_instances.size()); |
| 373 | cam->checkSpheresInFrustum(patch.detail_instances.size(), &patch.detail_instance_origins_x[0], &patch.detail_instance_origins_y[0], &patch.detail_instance_origins_z[0], model.bounding_sphere_radius, cull_dist_squared, &is_visible[0]); |
| 374 | for (int l = 0, len = patch.detail_instances.size(); l < len; ++l) { |
nothing calls this directly
no test coverage detected