1

I am trying to implement a 2D selection window that can select the 3D vertices inside the 2D window (indicated by dashed cyan rectangle). Each of my 3D models is currently a composite group of MeshView's, one MeshView per face. My plan was to iterate over each face (MeshView) and check if the 2D bounds intersect with the selection box bounds (I am planning to update this later using an Atlas texture to reduce the amount of meshes, but for now I just want the selection mechanism working).

Currently I have the following, but this isn't correct.

 val selectionBounds = selectionRectangle.boundsInParent
 val localBounds = meshView.localToScene(meshView.boundsInLocal, true)
 if (selectionBounds.intersects(localBounds))
     // do something with the mesh in meshView

My subscene contains a perspective camera, now I saw two useful posts:

  1. Convert coordinates from 3D scene to 2D overlay
  2. How to get 2D coordinates on window for 3D object in javafx

I think I have to first project the meshView's bounds properly using my perspective camera. But I am unsure how to proceed, do I have to project every 3D point in the local bounds to 2D as is done in referenced question 2 (above). Not very familiar with the math, or related concepts, any help would be appreciated.

(wink, wink MVP José)

Selection box example

EDIT 1:

After José's suggestion I added red bounding boxes for each meshview which gives the following result:

Offset

Apparently it adds some offset which appears to be the same regardless of the camera rotation. Here the red boxes are drawn around each meshview. Will investigate further..

EDIT 2:

I use a Pane which contains the SubScene and another Node. This is done to control the sizing of the SubScene and to reposition/resize the other Node accordingly by overriding the layoutChildren method, as such (this is in Kotlin):

override fun layoutChildren() {
    val subScene = subSceneProperty.get()
    if (subScene != null){
        subScene.width = width
        subScene.height = height
    }
    overlayRectangleGroup.resize(width, height)
    val nodeWidth = snapSize(overlayMiscGroup.prefWidth(-1.0))
    val nodeHeight = snapSize(overlayMiscGroup.prefHeight(-1.0))
    overlayMiscGroup.resizeRelocate(width - nodeWidth, 0.0, nodeWidth, nodeHeight)
}
  • 1
    If you are able to iterate all over your MeshViews and get their 2D bounding boxes like in question 1, then it is just a matter of checking which of them are inside the 2D selection box, which is what you have posted, btw. Why do you say it is wrong? I suggest you render a red rectangle for each MeshView as well, so you can verify you are doing it right. – José Pereda Jan 30 '21 at 21:32
  • @JoséPereda thanks, dope suggestion! I updated my post. It adds an offset to the right. I feel like this should be a relatively easy fix. Will update, but if u have any ideas please let me know :) – Stan van der Bend Jan 30 '21 at 21:41
  • 1
    Do you apply transforms to the MeshViews or only to the camera? If if is the latter case there shouldn't be an offset. Anyway, yes, should be easy to find out where it comes from: Is it always the same value? – José Pereda Jan 30 '21 at 21:45
  • @JoséPereda I add the rotate transforms to a Xform, add the camera to the same Xform, and I add the Xform to the subscene root. And it is always the same offset value, it's not relative to the camera position. – Stan van der Bend Jan 30 '21 at 21:56
  • 1
    Ideally, you should be able to find out where it comes from. So far, if it is always the same (and you know how to get it), you can simply subtract it to the red rectangles. – José Pereda Jan 30 '21 at 22:09
  • @JoséPereda The problem appears to be in the Pane I use to store the SubScene and the Rectangle. When I add the Rectangle directly to the Pane, its position remains absolute when I resize the Pane. I will investigate further tomorrow and update the main post. – Stan van der Bend Jan 30 '21 at 22:29
  • Why don't you use a Group? – José Pereda Jan 30 '21 at 22:31
  • @JoséPereda Ehm because I want the subscene to be resizeable. I found a class that handles this, which is a Pane containing the SubScene and another node on top of each other. This class extends Pane and overrides the layoutChildren function (used to resizeRelocate the other nodes and set the size of the subscene). I am not sure if the same can be achieved through a group. (Updated post with `layoutChildren` override.) – Stan van der Bend Jan 30 '21 at 22:38

0 Answers0