# Create AABB Cube from click-and-drag user rectangle? AABB OBB Collision Detection

I'm trying to create a 3D cube from rectangle drawn by ther user's mouse (think click-and-drag selection). My end goal is to use this to implement entity click-and-drag box selection. If you've played a traditional strategy game, basically that but everything is in 3D.

The interesting bit is that each entity in the scene has a potential 3D transform (translation/rotation/scale).

My approach is to create a cube in world space, based on where the user clicks (in screenspace).

1. Set min at the left-top of the mouserect (with a Z value matching the Camera's Z value).
2. Set the cube's maximum value to the right bottom (with a Z value of FAR, as defined by the projection matrix).
3. Use standard AABB vs OBB collision algorithm to determine if they overlap.

I'm having trouble with implementing this correctly. I have a working AABB vs OBB collision algorithm. I'm struggling with converting the user screen coordinates to a 3D cube.

Question 1: How would I go about this? Is there a better approach for this? (I'd like to ignore methods that involve comparing colors in the framebuffer).

Question 2: I have some code I've written that shows my understanding of the problem, maybe it's obvious what I'm doing wrong?

Question 3: Do you know of any example code doing this?

// NEAR, FAR values the proj matrix was constructed with
#define NEAR -500
#define FAR  +500

// Here invert the viewport Y component (glUnproject expects (x,y) to be in the lower-left of the
// screen)
auto vp        = viewport.size_vec4();
vp.y = vp.w - vp.y;

// The next bit is what I'm having trouble with.
// GOAL1: Convert the LEFT_TOP of the mouse-drawn rect from screen-space to world-space.
auto const lt  = mouse_rect.left_top();
auto const lt3 = glm::vec3{lt, 0};
glm::vec3 const mmin = glm::unProject(lt3, view, proj, vp);

// GOAL2: Convert the RIGHT_BOTTOM of the mouse-drawn rect from screen-space to world-space, but
// with a Z value equal to FAR.
auto const rb             = mouse_rect.right_bottom();
auto const rb3            = glm::vec3{rb, FAR};
glm::vec3 const mmax      = glm::unProject(rb3, view, proj, vp);

// Combine min/max to create a cube with
// min => User drawn rect left-top with Z at NEAR.
// max => right-bottom with Z at FAR.
Cube const mouse_cube{mmin, mmax};

// Determine whether the mouse is overlapping the cube.
auto const cube_mouserect_overlap = [&](auto const& cube_entity) {
auto const& cube        = cube_entity.cube();
auto tr                 = cube_entity.transform();
auto const obb_onscreen = OBB::from_cube_transform(cube, tr);

Transform mouse_tr;
auto const obb_mouse = OBB::from_cube_transform(mouse_cube, mouse_tr);
return collision::overlap(obb_onscreen, obb_mouse);
};

for (auto &ce : cube_ents) {
ce.selected = cube_mouserect_overlap(ce);
}


Thanks!