DXEventManager3DWrapper doesn't work with EllipseLineVisual3D
#1
originally, i use EventManager3D of powerToy.  every thing works fine.
but when I change it to DXEngine.
just some Visual3D object work with mouse events.

I create a common function to assign general mouse event handler to objects.

when I input TextBlockVisual3D or CircleVisual3D, it works, but if I input CornerWireBoxVisual3D or EllipseLineVisual3D, no any mouse handler triggered, procedure even not stopped in any breakpoints inside these mouse handlers.
 
#2
Hit testing (also EventManage3D) of 3D lines work in WPF 3D rendering because there the Ab3d.PowerToys library converts the 3D line into a standard GeometryModel3D object (this object is then updated on each camera change). When you have many 3D lines, then this is a very slow process. 

When the 3D scene is rendered with Ab3d.DXEngine, then the graphics card generates the geometry for the lines. This is much much faster and allows rendering millions of 3D lines. But because no GeometryModel3D is created for such lines, the 3D hit testing does not work any more.

You cannot have both - super fast 3D lines rendering and standard 3D hit testing.

If you are not rendering a lot of 3D lines (you are using DXEngine for some other reason - for example many other 3D objects), then you can disable hardware accelerated 3D lines. This can be done with setting HardwareAccelerate3DLines property on DXScene to false:

Code:
_dxViewportView.DXSceneDeviceCreated += delegate(object sender, EventArgs args)
{
  if (_dxViewportView.DXScene != null) // Can be null in WPF 3D rendering (used as fallback by default)
      _dxViewportView.DXScene.HardwareAccelerate3DLines = false;
};


Another option is to use Ab3d.Utilities.LineSelectorData from Ab3d.PowerToys library - this is a helper class that is meant to help user to select 3D lines. The problem with 3D lines for the application users is that they are usually thick and the user can have some problems to put the mouse exactly on a line. Therefore this class support selecting the closest 3D line - so you can decide how close the user need to be to select a 3D line. See the sample in Ab3d.PowerToys sample project for more info.

This class works only with 3D lines and polylines - not with CornerWireBoxVisual3D or EllipseLineVisual3D.

To support that you would need to manually create the lines needed for those two objects. Here is the code that does that:

CornerWireBoxVisual3D:
Code:
       /// <summary>
       /// Creates this Model3D
       /// </summary>
       protected override void CreateModel()
       {
           var centerPosition      = this.CenterPosition;
           var size                = this.Size;
           var isLineLengthPercent = this.IsLineLengthPercent;
           var lineLength          = this.LineLength;


           
           
           // In case one size component is 0, we create only a rectangle (8 positions instead of 24 for the whole box)
           if (MathUtils.IsZero(size.X) || MathUtils.IsZero(size.Y) || MathUtils.IsZero(size.Z))
           {
               // Optimize access
               double x = centerPosition.X - size.X / 2;
               double y = centerPosition.Y - size.Y / 2;
               double z = centerPosition.Z - size.Z / 2;

               double maxX = x + size.X;
               double maxY = y + size.Y;
               double maxZ = z + size.Z;

               Point3D p1, p2, p3, p4;
               var multiPolylines = new List<Point3DCollection>();

               if (MathUtils.IsZero(size.X))
               {
                   p1 = new Point3D(x,    y, z);
                   p2 = new Point3D(x, maxY, z);
                   p3 = new Point3D(x, maxY, maxZ);
                   p4 = new Point3D(x,    y, maxZ);
               }
               else if (MathUtils.IsZero(size.Y))
               {
                   p1 = new Point3D(x,    y, z);
                   p2 = new Point3D(maxX, y, z);
                   p3 = new Point3D(maxX, y, maxZ);
                   p4 = new Point3D(x,    y, maxZ);
               }
               else //if (MathUtils.IsZero(size.Z))
               {
                   p1 = new Point3D(x,    y, z);
                   p2 = new Point3D(x,    maxY, z);
                   p3 = new Point3D(maxX, maxY, z);
                   p4 = new Point3D(maxX, y, z);
               }

               var direction1 = p2 - p1;
               var length1 = direction1.Length;
               direction1 /= length1;

               var direction2 = p3 - p2;
               var length2 = direction1.Length;
               direction2 /= length2;

               if (isLineLengthPercent)
               {
                   direction1 *= length1 * lineLength;
                   direction2 *= length2 * lineLength;
               }
               else
               {
                   direction1 *= lineLength;
                   direction2 *= lineLength;
               }

               var oneCornerPositions = new Point3DCollection(3);
               oneCornerPositions.Add(p1 + direction2);
               oneCornerPositions.Add(p1);
               oneCornerPositions.Add(p1 + direction1);
               multiPolylines.Add(oneCornerPositions);

               oneCornerPositions = new Point3DCollection(3);
               oneCornerPositions.Add(p2 - direction1);
               oneCornerPositions.Add(p2);
               oneCornerPositions.Add(p2 + direction2);
               multiPolylines.Add(oneCornerPositions);

               oneCornerPositions = new Point3DCollection(3);
               oneCornerPositions.Add(p3 - direction2);
               oneCornerPositions.Add(p3);
               oneCornerPositions.Add(p3 - direction1);
               multiPolylines.Add(oneCornerPositions);

               oneCornerPositions = new Point3DCollection(3);
               oneCornerPositions.Add(p4 + direction1);
               oneCornerPositions.Add(p4);
               oneCornerPositions.Add(p4 - direction2);
               multiPolylines.Add(oneCornerPositions);


               this.Content = Ab3d.Models.Line3DFactory.CreateMultiPolyLine3D(
                                                            multiPolylines,
                                                            this.LineThickness,
                                                            this.LineColor,
                                                            LineCap.Flat, LineCap.Flat,
                                                            miterLimit: 6.0,
                                                            parentVisual3D: this);

               return;
           }


           // All size components are bigger then 0 => create a box with 24 positions
           var positions = Ab3d.Models.Line3DFactory.CreateWireBox3DPositions(this.CenterPosition, size);


           // Now divide each line into two lines - one at the start position and one at the end position
           var cornerLinePositions = new Point3DCollection(positions.Count * 2);

           for (int i = 0; i < positions.Count; i += 2)
           {
               Point3D p1 = positions[i];
               Point3D p4 = positions[i + 1];

               var direction = p4 - p1;
               var length    = direction.Length;
               direction     = direction / length; // Normalize


               Point3D p2, p3;

               if (isLineLengthPercent)
               {
                   p2 = p1 + direction * length * lineLength;
                   p3 = p4 - direction * length * lineLength;
               }
               else
               {
                   p2 = p1 + direction * lineLength;
                   p3 = p4 - direction * lineLength;
               }

               cornerLinePositions.Add(p1);
               cornerLinePositions.Add(p2);
               cornerLinePositions.Add(p3);
               cornerLinePositions.Add(p4);
           }

           SetPositions(cornerLinePositions, raisePropertyChangedEvent: false);

           this.Content = Ab3d.Models.Line3DFactory.CreateMultiLine3D(cornerLinePositions, this.LineThickness, this.LineColor, this);
       }

EllipseLineVisual3D:
Code:
       /// <summary>
       /// Creates this Model3D
       /// </summary>
       protected override void CreateModel()
       {
           var segments = this.Segments;

           bool createNewPositions = _positions == null;
           if (createNewPositions)
           {
               _positions = new Point3DCollection(segments + 1);
           }
           else
           {
               SetPositions(null, raisePropertyChangedEvent: false); // Disconnect _positions, otherwise each change on the collection will trigger OnPropertyChanged event
               _positions.Clear();
           }

           var ellipseNormalVector = Vector3D.CrossProduct(WidthDirection, HeightDirection);
           Ab3d.Utilities.CurvesHelper.AddArc3DPoints(CenterPosition, ellipseNormalVector, WidthDirection, Width * 0.5, Height * 0.5, 0, 360, segments, _positions);

           this.Content = Ab3d.Models.Line3DFactory.CreatePolyLine3D(_positions, LineThickness, LineColor,
                                                                     areLinesConnected: true, isClosed: false,
                                                                     startLineCap: LineCap.Flat, endLineCap: LineCap.Flat,
                                                                     lineSegmentsCountForArrowLength: 0,
                                                                     miterLimit: Ab3d.Meshes.BaseConnectedLinesMesh3D.DefaultMiterLimit,
                                                                     parentVisual3D: this, parentViewport3D: null);
       }


You may also think if you really want to have mouse events subscribed to helper 3D lines such as CornerWireBoxVisual3D - I find this quite unusual.
Andrej Benedik
#3
thank you.

one more question please.

I can use mouse move, down DXevents, but why can't I use Drag DXevent. since it works with powerToy.
#4
The DXEventaManager3DWrapper samples shows that with DXEventaManager3DWrapper you can use the MouseDrag and IsDragSurface.
Andrej Benedik
  


Forum Jump:


Users browsing this thread:
1 Guest(s)