ADD: BVH Selection system completed

This commit is contained in:
2025-11-20 00:56:14 +09:00
parent 0fe7c0f975
commit b85bb1b59b

View File

@@ -283,11 +283,17 @@ namespace
const glm::vec3 &rayDir, const glm::vec3 &rayDir,
const RenderObject &obj, const RenderObject &obj,
glm::vec3 &outWorldHit, glm::vec3 &outWorldHit,
BoundsHitDebug *debug) BoundsHitDebug *debug,
MeshBVHPickHit *outMeshHit)
{ {
const Bounds &bounds = obj.bounds; const Bounds &bounds = obj.bounds;
const glm::mat4 &worldTransform = obj.transform; const glm::mat4 &worldTransform = obj.transform;
if (outMeshHit)
{
*outMeshHit = {};
}
// Non-pickable object. // Non-pickable object.
if (bounds.type == BoundsType::None) if (bounds.type == BoundsType::None)
{ {
@@ -324,29 +330,41 @@ namespace
} }
case BoundsType::Mesh: case BoundsType::Mesh:
{ {
// Try high-precision mesh BVH first when available, then fall back to box. // For mesh bounds we rely solely on the CPU mesh BVH.
if (obj.sourceMesh && obj.sourceMesh->bvh) // If there is no BVH or the BVH misses, the object is
// treated as not hit by this ray (no coarse box fallback).
if (!obj.sourceMesh || !obj.sourceMesh->bvh)
{ {
return false;
}
if (debug) if (debug)
{ {
debug->usedBVH = true; debug->usedBVH = true;
} }
MeshBVHPickHit meshHit{}; MeshBVHPickHit meshHit{};
if (intersect_ray_mesh_bvh(*obj.sourceMesh->bvh, worldTransform, rayOrigin, rayDir, meshHit)) if (!intersect_ray_mesh_bvh(*obj.sourceMesh->bvh, worldTransform, rayOrigin, rayDir, meshHit))
{ {
if (debug)
{
// BVH was queried but produced no hit.
debug->fallbackBox = true;
}
return false;
}
if (debug) if (debug)
{ {
debug->bvhHit = true; debug->bvhHit = true;
} }
outWorldHit = meshHit.worldPos; outWorldHit = meshHit.worldPos;
return true; if (outMeshHit)
}
if (debug)
{ {
debug->fallbackBox = true; *outMeshHit = meshHit;
} }
} return true;
// return intersect_ray_box(rayOrigin, rayDir, bounds, worldTransform, outWorldHit);
} }
case BoundsType::Box: case BoundsType::Box:
default: default:
@@ -455,7 +473,8 @@ bool SceneManager::pick(const glm::vec2 &mousePosPixels, RenderObject &outObject
{ {
glm::vec3 hitPos{}; glm::vec3 hitPos{};
BoundsHitDebug localDebug{}; BoundsHitDebug localDebug{};
if (!intersect_ray_bounds(rayOrigin, rayDir, obj, hitPos, &localDebug)) MeshBVHPickHit localMeshHit{};
if (!intersect_ray_bounds(rayOrigin, rayDir, obj, hitPos, &localDebug, &localMeshHit))
{ {
continue; continue;
} }
@@ -466,6 +485,16 @@ bool SceneManager::pick(const glm::vec2 &mousePosPixels, RenderObject &outObject
bestDist2 = d2; bestDist2 = d2;
bestHitPos = hitPos; bestHitPos = hitPos;
outObject = obj; outObject = obj;
// If we have a precise mesh BVH hit, refine the picked
// primitive to the exact triangle instead of the whole surface.
if (localMeshHit.hit && outObject.sourceMesh && outObject.sourceMesh->bvh)
{
outObject.firstIndex = localMeshHit.firstIndex;
outObject.indexCount = 3;
outObject.surfaceIndex = localMeshHit.surfaceIndex;
}
anyHit = true; anyHit = true;
// Capture debug info for the best hit so far. // Capture debug info for the best hit so far.