| 65 | } |
| 66 | |
| 67 | static bool Search(Actor* actor, GeometryLookup& lookup) |
| 68 | { |
| 69 | // Early out if object is not intersecting with the foliage brush bounds |
| 70 | if (!actor->GetIsActive() || !actor->GetBox().Intersects(lookup.Brush)) |
| 71 | return true; |
| 72 | |
| 73 | const auto brush = lookup.Brush; |
| 74 | if (const auto* staticModel = dynamic_cast<StaticModel*>(actor)) |
| 75 | { |
| 76 | // Skip if model is not loaded |
| 77 | if (staticModel->Model == nullptr || staticModel->Model->WaitForLoaded() || staticModel->Model->GetLoadedLODs() == 0) |
| 78 | return true; |
| 79 | |
| 80 | PROFILE_CPU_NAMED("StaticModel"); |
| 81 | |
| 82 | // Check model meshes |
| 83 | Transform transform = staticModel->GetTransform(); |
| 84 | Matrix worldMatrix; |
| 85 | transform.GetWorld(worldMatrix); |
| 86 | const bool isDeterminantPositive = transform.GetDeterminant() >= 0.0f; |
| 87 | auto& lod = staticModel->Model->LODs[0]; |
| 88 | for (int32 meshIndex = 0; meshIndex < lod.Meshes.Count(); meshIndex++) |
| 89 | { |
| 90 | auto& mesh = lod.Meshes[meshIndex]; |
| 91 | auto& proxy = mesh.GetCollisionProxy(); |
| 92 | |
| 93 | // Check every triangle |
| 94 | for (int32 triangleIndex = 0; triangleIndex < proxy.Triangles.Count(); triangleIndex++) |
| 95 | { |
| 96 | auto t = proxy.Triangles[triangleIndex]; |
| 97 | |
| 98 | // Transform triangle vertices from mesh space to world space |
| 99 | Vector3 t0, t1, t2; |
| 100 | Vector3::Transform(t.V0, worldMatrix, t0); |
| 101 | Vector3::Transform(t.V1, worldMatrix, t1); |
| 102 | Vector3::Transform(t.V2, worldMatrix, t2); |
| 103 | |
| 104 | // Check if triangles intersects with the brush |
| 105 | if (CollisionsHelper::SphereIntersectsTriangle(brush, t0, t1, t2)) |
| 106 | { |
| 107 | lookup.Triangles.Add(GeometryTriangle(isDeterminantPositive, t0, t1, t2)); |
| 108 | } |
| 109 | } |
| 110 | } |
| 111 | } |
| 112 | else if (const auto* terrain = dynamic_cast<Terrain*>(actor)) |
| 113 | { |
| 114 | const bool isDeterminantPositive = terrain->GetTransform().GetDeterminant() >= 0.0f; |
| 115 | |
| 116 | PROFILE_CPU_NAMED("Terrain"); |
| 117 | |
| 118 | // Check every patch |
| 119 | for (int32 patchIndex = 0; patchIndex < terrain->GetPatchesCount(); patchIndex++) |
| 120 | { |
| 121 | auto patch = terrain->GetPatch(patchIndex); |
| 122 | |
| 123 | auto& triangles = lookup.TerrainCache; |
| 124 | patch->GetCollisionTriangles(brush, triangles); |
nothing calls this directly
no test coverage detected