Box/Lasso selection
#1
I'd like to implement a box selection/lasso selection for a 3d scene editor. I think the box selection should be pretty simple if implemented using plane/bounding box collision. But doing the same for lasso is not the right way. So here are the questions:

1. I know it's possible to create rendering steps in DXEngine. Which steps need to be implemented to achieve rendering the objects with an ID instead of color, reading the texture back with no post processing and multi sampling?

2. Is there a method that would allow rendering the scene on demand but with replacement shader? Let's say I have created a shader that converts ID of my object to color (even better would be if such shader already exists) and I would call Render.DrawImmediate(root, replacementShader)?


3. In the case of physics, is there a method to detect if mesh is at least partially on the side of a plane? Something like the Plane.Slice* methods but without the slicing...

Thanks,
Janovsky Roman
#2
Your question was a little bit more complicated so I needed to find some more free time to answer it.

I have created a sample that demonstrates how to render object ids to a bitmap.

To test the sample, add the attached two files to the DXEngine samples project into the DXEngineAdvanced folder.
Then open the samples.xml file (on the root) and add the following line under the DXEngineAdvanced section:
<Sample Page="DXEngineAdvanced/ObjectIdRendering.xaml" Title="ObjectId rendering" Description=""/>

Start the samples.

The sample is using a custom rendering step that renders each object with a SolidColorEffect where the color is set from the object index. This way you can get the rendered object back from the color - see the comment in the same for more info.


Instead of using objects id map, you could also convert all 3D positions into 2D positions with Camera.Point3DTo2D method. When you have all positions in 2D space, then it is much easier to solve the problem of determining which positions are inside the lasso or box region. Note that you would need to calculate the 2D positions only after the camera is changed; and if you have your meshes prepared in such a way (Frozen, or have copies of positions), then you could do that in a background thread while the user is drawing the lasso.

Instead of using SolidColorEffect, you could also use some other custom shader defined by you - see the advanced section of the DXEngine samples for more samples on how to do that (for example the CustomShaderMaterialSample).


To detect if mesh is partially on a side of a plane, I would first do a BoundingBox / Plane intersection test (Ab3d.Utilities.Plane.GetIntersectionType method). If this returns PlaneIntersectionType.Spanning, then you would need to go through all positions of the mesh and check if some points are in front of the plane and some are behind - you can use the Plane.GetDistance method (positive value: position is in front of the plane; negative: back; zero: on the plane).

To speed up things you can inline the GetDistance method:
Code:
       /// <summary>
       /// Returns signed distance of the specified position from this Plane.
       /// If distance is positive, then position is in front of the plane (determined by the direction of the plane's normal).
       /// If distance is negative, then position is behind the plane.
       /// If distance is zero, then position lies on the plane.
       /// </summary>
       /// <param name="position">position as Point3D</param>
       /// <returns>signed distance of the specified position from this Plane</returns>
       public double GetDistance(Point3D position)
       {
           //return Vector3D.DotProduct(Normal, position) + d; // this cannot be used because Vector3D.DotProduct takes only two Vector3D parameters
           return A * position.X + B * position.Y + C * position.Z + D;
       }
EDITED:
After some additional checks I have found out that the GetObjectIdColor4 method in the attached ObjectIdRendering.xaml.cs file was not correct. The method did not correctly transformed the renderingQueueIndex into Color. This has been fixed.
I have also added a method that converts the Color4 back into the renderingQueueIndex and objectIndex.


Attached Files
.xaml   ObjectIdRendering.xaml (Size: 2.92 KB / Downloads: 3)
.cs   ObjectIdRendering.xaml.cs (Size: 11.49 KB / Downloads: 0)
Andrej Benedik
#3
Thank you, you explained it exhaustively. This should be more than enough to get me on the right track. 
In the sample, you mention dxScene.StandardGeometryRenderingQueue: Is it the opaque geometry with the transparent geometry having its own queue?
#4
Yes, all the transparent geometry is in DXScene.TransparentRenderingQueue - you can skip rendering them into object_id texture. 

When going through all RenderingQueues you can also check the ContainsTransparentObjects property - if it is true, then this queue contains transparent objects (currently only DXScene.TransparentRendering).
Andrej Benedik
  


Forum Jump:


Users browsing this thread:
1 Guest(s)