AB4D Forum

Full Version: Fixed width line
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi,
How can I create a line with fixed width, which will not change when I move the camera? I do not want my lines to scale up when I move the camera away.
I have tried using Ab3d.Visuals.LineArcVisual3D and Ab3d.Models.Line3DFactory.CreateLine3D(), but the result was the same.
I think Ab3d.Utilities.LinesUpdater.Instance.UnregisterLine() might do the work, but I can't get it to work properly.
Any hints?
You can create a 3D plane with PlaneVisual3D or PlaneMesh3D - you can than set Size to something that would look like a line - for example (3, 500).

I hope this is what you are looking for.
(03-27-2013, 04:46 PM)abenedik Wrote: [ -> ]You can create a 3D plane with PlaneVisual3D or PlaneMesh3D - you can than set Size to something that would look like a line - for example (3, 500).

I hope this is what you are looking for.

Thanks, this works for simple 3d line, but I also need a solution for other "line base" visuals like: LineArcVisual3D, PolyLineVisual3D, TextVisual3D. They all are influenced by LineUpdater, which changes theirs thickness automatically or when Refres() is called.
Is there a way to force those visuals to create their geometries with "original thickness", so I can just Unregister them from LineUpdater? This way I owuld get a static visual, which won't change when I move my camera?
I understand now.

You can achieve that with the following:

- first you need to disable LinesUpdater - this can be done in the class constructor with:
Ab3d.Utilities.LinesUpdater.Instance.UpdateMode = Ab3d.Common.Utilities.LinesUpdaterMode.Never;

- than after you added your 3D lines you need to manually refresh the camera and LinesUpdater. For example if you have defined your lines in XAML, than you can add the following code to OnLoad event handler:

Camera1.Refresh();
Ab3d.Utilities.LinesUpdater.Instance.Refresh();

Note that this will not work if called from constructor - you need to call this after (or in) Loaded event.

I hope that this is what you are looking for - note that if the camera will be changed after that the lines will look strange - they are created for specific camera angle.
Is there any other solution, which does not require creating a window and displaying it (so the Loaded event fires)?
I have tried inheriting LineVisual3D to expose CreateModel() method, but calling it creates model geometry with NaN position values.
I have checked the code again and found a very interesting cause of the problem - the MeshGeometry for the 3D lines is generated based on the camera position - actually a camera matrix is calculated from the current camera position - but we also need aspect ration of the viewport where we are showing the 3D scene - so we also need the size of the Viewport3D. By default Viewport3D's ActualWidth and ActualHeight are used, but when they are not set the Width and Height can be used as fallback.

So the only thing that was missing was to set the Width and Height for Viewport.

So with that knowledge we can create the geometry anywhere in the code (no need to show anything) - the following creates a 3D Arc:
Code:
var viewport3D = new Viewport3D();
            viewport3D.Width = 800;
            viewport3D.Height = 600;

            var targetPositionCamera = new TargetPositionCamera();
            targetPositionCamera.TargetPosition = new Point3D(0, 0, 0);
            targetPositionCamera.Distance = 200;
            targetPositionCamera.Attitude = -30;
            targetPositionCamera.TargetViewport3D = viewport3D;

            targetPositionCamera.Refresh();

            var lineArcVisual3D = new LineArcVisual3D();
            lineArcVisual3D.BeginInit();
            lineArcVisual3D.Radius = 30;
            lineArcVisual3D.StartAngle = 0;
            lineArcVisual3D.EndAngle = 90;
            lineArcVisual3D.CircleNormal = new Vector3D(0, 0, 1);
            lineArcVisual3D.ZeroAngleDirection = new Vector3D(1, 0, 0);
            lineArcVisual3D.LineThickness = 3;
            lineArcVisual3D.LineColor = Colors.Red;
            lineArcVisual3D.EndInit();

            viewport3D.Children.Add(lineArcVisual3D);

After the lineArcVisual3D is added to viewport3D, the Content of the lineArcVisual3D will contain an actual GeometryModel3D.

IMPORTANT:
I used BeginInit and EndInit when setting properties on LineArcVisual3D. This can be a big performance optimization - without that the 3D geometry can be recreated multiple times (in our case we would get 6 GeometryModel3D). When using BeginInit and EndInit the geometry is recreated only once.
Hi, that is exactly what I was looking for. Thanks for help.