I'm using the excellent code provided in threex to allow me to capture clicks on various objects in my scene, which allows me to select them. This works with no issue.
I'd like to extend the selection functionality, where the user can draw a selection box(working), and I can detect all the objects in the scene which are rendered in this selection.
Looking at threex / three, the general onclick algorithm seems to be:
project mouse co-ords to Ray
using ray.intersectObjects(scene), it tests each object in the scene for ray
intersection
This works for a single '1D' ray in the system, but there doesn't seem to be an easy way to modify it to work with a selection box.
Before I attempt to extend this mechanism to work with a selection frustum, is there an alternate / existing facility?
The answer to your question is no, there is no such existing facility.
I would not use Raycaster.intersects() for this.
Probably the easiest thing to do is to assign a 2D screenCoords property to each object, and set it equal to the screen projection of the object's world position. Search this site for how to do that.
Then, consider as selected, those objects whose screenCoords are inside the selection box in screen space.
If you need complete containment, then you have to either do the above for each vertex, or use something like a bounding sphere as an approximation.
three.js r.58
Related
I know that with QObjectPicker I can mouse pick a single entity. But how can I select multiple objects by drawing a rectangle on the screen?
I think this is actually pretty complicated. But here are my two cents:
If you only need to be able to select unoccluded objects
(i.e. don't need to select occluded ones) you could add a second frame graph branch to your existing one and draw each object with a unique color but to an offscreen texture. Then retrieve this texture, check which colors lie within the drawn rectangle and retrieve the corresponding objects and select them (compare to this question/answer).
I'm not sure how well this works in Qt3D because I've always had some issues with QRenderCapture. It didn't seem to have an impact where I added it in the frame graph, i.e. always captured the last state so maybe even if you have multiple render targets it might capture the wrong one etc. Qt3D is still in a pretty rough state I'd say.
If you need an example of how to render to an offscreen texture check out my example on GitHub.
If you need to be able to select occluded objects too
then it gets pretty complicated. I'm just providing some ideas here. I don't know if they will work.
If you don't have that many objects maybe you could implement the idea from above for each single object. I.e. for each object you have an offscreen frame graph branch that filters out all other objects. Then you could check each rendered texture for the rectangle drawn with the mouse. But again I'm not sure how well this works with Qt3D and if you have many objects (like in a game) it will probably crash because of the many offscreen textures.
You could also implement something like "inverse" frustum culling. In frustum culling, you omit rendering objects that lie outside the view frustum of the camera. You could compute a frustum using the rectangle coordinates drawn with the mouse. Check out the QFrustumCulling code. You would need to compute the planes differently of course, using a modified view matrix. When the user draws the rectangle, compute the frustum and check all objects. Unfortunately, this also selects objects whose bounding sphere intersects with the frustum, even though you might visible not touch any part of the object. If that bothers you, you could directly select all objects whose sphere is completely within the frustum and for all objects which only partly intersect do the intersection computation on a per-triangle basis and exit computation for the current object as soon as a triangle intersects the frustum. Depending on the number of triangles this could be very costly computational-wise.
I'd definitely stick to being able to select only unoccluded objects especially because picking in OpenGL seems to be realized by drawing the ojbects with colors these days.
I have a problem I don't known how I can select the position of the selected inside scene and move camera into it
I found a project sample, and I want to build an example like it
Sample project
Thank you so much!
You basically solve this problem in two steps:
First, you have to make 3D objects selectable which can be done via raycasting. There are many official examples that demonstrate 3D interaction based on raycasting, for example:
https://threejs.org/examples/webgl_interactive_cubes
If you know that a certain 3D object was clicked, you animate the camera from its current position to a defined target position. The possible target positions can be defined prior or you compute the in some way on the fly based on the object's bounding volume and the current camera position. The actual animation can be done in many ways. One approach is using a tweening engine like tween.js. Check out the following example to see how it is used together with three.js:
https://threejs.org/examples/css3d_periodictable
I'm creating a 3D model editor application using THREE.js where you can load a CAD model and have it display on the screen. You can pan, zoom, rotate the camera anywhere around in the scene to view the CAD model from any angle.
I want to add support to be able to draw an arbitrary rectangle on the screen (marquee select box) and anything inside this box I'd like to become selected.
What is a good algorithm to use for this operation?
My first thought was to take every loaded CAD part (that can be selected), and project its bounding box onto the screen. Then test each of these projected bounding boxes to the selection box drawn on the screen for matches. This should work, however I'm worried it would be very slow for large CAD models with 1000's of selectable parts.
Is there a better way to do marquee selections in 3D? Can raycasting somehow be used to speed up the selections?
Without knowing more details about your cad models it'll be a bit hard to give exactly relevant suggestions but I can suggest a few things I might try.
Use Hierarchical Bounding Boxes
If you have a multi-level tree of meshes you can generate bounding boxes for the non-leaf nodes of the tree. This isn't supported directly in THREE but you can manually create and check against these objects before checking if the child objects are within the marquee.
If your tree isn't spatially organized very well or is very flat then you can build an oct-tree and traverse the oct-tree nodes before checking the meshes.
Of course these data structures have to be updated whenever meshes move in your CAD model.
Cache World Bounds
If you cache versions of the bounding boxes on all the meshes in world space then instead of projecting the bounds into screen space you can create a frustum from the marquee in world space and check the all the mesh bounds without having to do any transformation of those boxes.
Asynchronous Checking
Instead of gathering all the intersected bounds on a single frame you could gather them up over multiple frames if it is taking a long time.
Unfortunately I don't think raycasting can do a whole lot for you here.
Hopefully that helps!
I have a cupboard with 9 boxes. On one of them I have animation, which open / close box. It is only change X coordinate of the box, but I can't apply this animation to another boxes, because animation will move it to the coordinate of the first box.
In the debug mode parameter Keep Original Position XZ are disabled. Can't understand, what is wrong.
Should I create 9 similar animations for 9 boxes?
I know that it is possible to animate stuffs using relative positions on the UI when using the anchors, but there does not seem to be any clean solution for 3D objects... This post offers what seem to be the "best" solution for now (it uses an empty parent transform to move the animated object correctly...)
You should be able to apply the animation to any object. I would recommend making a prefab of the "box" with the animation attached, then using the prefab for each. Honestly I don't have much experience with animations of 3D objects, but even my 2D animations are in a 3D space, and each object animates properly with the same animations individually regardless of their location.
I am working on a Project in which I have to create an editor, which can create and transform ellipses. I understand all the necessary programming to do it with a GUI for the transformations, but it looks and feels better when all the Ellipses can be transformed by mouse. I know how to drag them, so that shouldn't be a problem, but for the transformation of the 2 radii and the rotation I have no clue.
An sketch of what I'm looking for:
If the grabbing points are visible or not doesn't matter. Do any of you have a knowledge of how to do this easily or if there already is code out there?
I didn't find anything on Google(may be my average search skills though).
Every Node in JavaFX has convenience methods to set transformations. So all you have to do is to register your desired input handlers aplly some transforms based on the mouse position.
ellipse.setRadiusY( radiusY );
ellipse.setRadiusX( radiusX );
ellipse.setRotate( angle );
See a full example.