| 673 | #endif // defined(USE_SSE) |
| 674 | |
| 675 | void Camera::checkSpheresInFrustum(int count, float* where_x, float* where_y, float* where_z, float radius, float cull_distance_squared, uint32_t* is_visible_result) const { |
| 676 | const vec3 cam_pos = GetPos(); |
| 677 | int i = 0; |
| 678 | |
| 679 | #if defined(USE_SSE) |
| 680 | // This loop exhausts all up to the last 0-3 |
| 681 | const __m128 all_true = _mm_set1_ps((float)0xFFFFFFFF); |
| 682 | const __m128 neg_radius4 = _mm_set1_ps(-radius); |
| 683 | |
| 684 | const __m128 cam_pos_x4 = _mm_set1_ps(cam_pos.x()); |
| 685 | const __m128 cam_pos_y4 = _mm_set1_ps(cam_pos.y()); |
| 686 | const __m128 cam_pos_z4 = _mm_set1_ps(cam_pos.z()); |
| 687 | const __m128 cull_distance_squared4 = _mm_set1_ps(cull_distance_squared); |
| 688 | |
| 689 | for (; i <= count - 4; i += 4) { |
| 690 | const __m128 where_x4 = _mm_load_ps(&where_x[i]); |
| 691 | const __m128 where_y4 = _mm_load_ps(&where_y[i]); |
| 692 | const __m128 where_z4 = _mm_load_ps(&where_z[i]); |
| 693 | |
| 694 | __m128 inside = all_true; |
| 695 | |
| 696 | __m128 distance_squared = simd_distance_squared(where_x4, where_y4, where_z4, cam_pos_x4, cam_pos_y4, cam_pos_z4); |
| 697 | __m128 is_in_view_distance = _mm_cmplt_ps(distance_squared, cull_distance_squared4); |
| 698 | inside = _mm_and_ps(inside, is_in_view_distance); |
| 699 | |
| 700 | for (const auto& simdFrustumPlane : simdFrustumPlanes) { |
| 701 | const __m128& plane_n_x4 = simdFrustumPlane.normal_x; |
| 702 | const __m128& plane_n_y4 = simdFrustumPlane.normal_y; |
| 703 | const __m128& plane_n_z4 = simdFrustumPlane.normal_z; |
| 704 | __m128 n_dot_pos = simd_dot_product(where_x4, where_y4, where_z4, plane_n_x4, plane_n_y4, plane_n_z4); |
| 705 | |
| 706 | __m128 plane_test = _mm_cmpgt_ps(_mm_add_ps(n_dot_pos, simdFrustumPlane.d), neg_radius4); |
| 707 | inside = _mm_and_ps(inside, plane_test); |
| 708 | } |
| 709 | |
| 710 | _mm_store_ps((float*)&is_visible_result[i], inside); |
| 711 | } |
| 712 | #endif // defined(USE_SSE) |
| 713 | |
| 714 | for (; i < count; ++i) { |
| 715 | bool inside = true; |
| 716 | |
| 717 | float center_to_cam[3] = { |
| 718 | where_x[i] - cam_pos.x(), |
| 719 | where_y[i] - cam_pos.y(), |
| 720 | where_z[i] - cam_pos.z(), |
| 721 | }; |
| 722 | float distance_squared = center_to_cam[0] * center_to_cam[0] + |
| 723 | center_to_cam[1] * center_to_cam[1] + |
| 724 | center_to_cam[2] * center_to_cam[2]; |
| 725 | |
| 726 | if (distance_squared < cull_distance_squared) { |
| 727 | for (auto frustumPlane : frustumPlanes) { |
| 728 | float n_dot_pos = |
| 729 | frustumPlane[0] * where_x[i] + |
| 730 | frustumPlane[1] * where_y[i] + |
| 731 | frustumPlane[2] * where_z[i]; |
| 732 | bool plane_test = n_dot_pos + frustumPlane[3] > -radius; |
no test coverage detected