create shape from an arbitrary closed loop on a 3d object - three.js

I'm currently building a 3D communications tool in three.js where people can highlight any area of a 3d object and comment on it.
The user should be able to draw a closed loop on the surface of a 3d object and the software will highlight the enclosed area.
I need to store this shape somehow and be able to detect it when a user clicks it again.
For example, the user might draw this:
I then need to figure out this enclosing shape:
Currently, I'm thinking of storing the loop as many line segments, and then calculating whether a user has clicking inside the shape by using some raycasting algorithm.
But I have no idea if this is efficient or how the raycasting will work.
Is there a more efficient algorithm or procedure out there?

Related

I need an algorithm to indentify created shapes on the ground and fill them(change the colors of the blocks within)

I am building a game where 8 players are spawned in an arena and each has their own color and they are suppose to roam around the arena(the blocks they walk on change to the player's color) with the purpose to fill as much of the arena's ground with their color.
When they create a shape they inside of the shape is also supposed to change to their color but I can't think of a way to actually implement this so I would really appreciate some help.
I broke down the process of implementing this into 2 steps:
Identify when a shape is created
Find all the blocks that are inside the perimeter of that shape an fill them
An example for shape that I would like to fill(The blue blocks are supposed to be the perimeter of the shape

Is it possible to select multiple objects with box selection?

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.

Three.js algorithm for marquee selecting in 3D scene

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!

select all objects in bounding box in three.js

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

How to determine top most object in 2d projection of 3d object?

I have a surface to which a set of 3d objects is drawn. The task is to determine an object by the given coordinates on the surface.
For example: some objects are drawn on the desktop application, I need to determine on which object user clicked.
Could you please advise, how such task is usually resolved? Am I need to create remember a top-most object for each pixel? I don't think it is the best approach.
Any thoughts are welcome!
Thanks!
The name for this task is picking (which ought to help you Google for more help on it). There are two main approaches:
Ray-casting: find the line that starts at the camera position and passes through the surface point you are interested in. (The line "under the mouse", or "under your finger" for a touch screen.) Depending on which 3D system you are using, there may be an API call to generate this line: for example Camera.ViewportPointToRay in Unity3D, or you may have to generate it yourself by inverting the camera transform. Find all the points of intersection between this line and the objects in your scene. Which of these points is closest to the near plane of the camera? You can use space partitioning to speed this up.
Rendering: do an extra render pass, in which instead of writing textures to the frame buffer, you record which objects were drawn. You don't do the render pass for the whole screen, you just do it for the area (e.g. the pixel) you are interested in. (This is GL_SELECT mode in OpenGL: see the Picking Tutorial for details.)
If you've described the surface somehow in 3D space, then the ray, defined by your point of observation and a 3D point that is a solution for where you clicked, should intersect one or more objects in your world, if indeed you clicked on one of them.
Given the equations for the surfaces of the objects, you can determine where this ray intersects the objects, if at all, since you also know the equation for the ray in the same coordinate system.
The object that has the closest intersection point to your point of observation (assuming you're looking at the objects from above) is the winner.

Resources