Exemple #1
0
        private void CreateInstanceText(InstancedTextNode instancedTextNode, Point3D centerPosition, Size3D size, int xCount, int yCount, int zCount, Color textColor, double textSize, string stringFormat = "({0:0} {1:0} {2:0})")
        {
            float xStep = xCount <= 1 ? 0 : (float)(size.X / (xCount - 1));
            float yStep = yCount <= 1 ? 0 : (float)(size.Y / (yCount - 1));
            float zStep = zCount <= 1 ? 0 : (float)(size.Z / (zCount - 1));

            for (int z = 0; z < zCount; z++)
            {
                float zPos = (float)(centerPosition.Z - (size.Z / 2.0) + (z * zStep));

                for (int y = 0; y < yCount; y++)
                {
                    float yPos = (float)(centerPosition.Y - (size.Y / 2.0) + (y * yStep));

                    for (int x = 0; x < xCount; x++)
                    {
                        float xPos = (float)(centerPosition.X - (size.X / 2.0) + (x * xStep));

                        string infoText = string.Format(stringFormat, xPos, yPos, zPos);

                        instancedTextNode.AddText(infoText, textColor, new Point3D(xPos, yPos, zPos), textSize, hasBackSide: true);
                    }
                }
            }
        }
Exemple #2
0
        private void DisposeInstancedTextNodes()
        {
            if (_instancedTextNode != null)
            {
                _instancedTextNode.Dispose();
                _instancedTextNode = null;
            }

            if (_instancedTextNode2 != null)
            {
                _instancedTextNode2.Dispose();
                _instancedTextNode2 = null;
            }
        }
Exemple #3
0
        private void CreateSimpleDemoScene()
        {
            // When using Ab3d.PowerToys and Ab3d.DXEngine, then the standard way to render text is to use TextBlockVisual3D.
            // It provides many options and easy positioning with Position / PositionType properties. See sample in the Ab3d.PowerToys samples project for more info.
            //
            // Here we also show how to setup the alpha-clip threshold that can be used when rendering with Ab3d.DXEngine.
            // This way we do not need to sort the TextBlockVisual3D by their distance to render them correctly.

            var textBlockVisual3D = new TextBlockVisual3D()
            {
                Text                   = "TextBlockVisual3D",
                Position               = new Point3D(-190, -50, 0),
                PositionType           = PositionTypes.BottomLeft,
                TextDirection          = new Vector3D(1, 0, 0),
                UpDirection            = new Vector3D(0, 1, 0),
                Size                   = new Size(80, 40),
                Background             = Brushes.Transparent,
                RenderBitmapSize       = new Size(256, 128),
                TextPadding            = new Thickness(5, 0, 5, 0),
                BorderBrush            = Brushes.Yellow,
                BorderThickness        = new Thickness(0, 2, 0, 2),
                IsBackSidedTextFlipped = true
            };

            // Because TextBlockVisual3D usually use transparent background the rules and limitations of rendering transparent objects apply when using multiple TextBlockVisual3D objects (see Alpha clipping sample for more info).
            // With Ab3d.DXEngine a very fast transparent objects sorting can be enabled by:
            // MainDXViewportView.DXScene.IsTransparencySortingEnabled
            //
            // But instead of using transparency sorting, we enable alpha-clipping (see Alpha clipping sample for more info):
            textBlockVisual3D.SetDXAttribute(DXAttributeType.Texture_AlphaClipThreshold, 0.15f);

            MainViewport.Children.Add(textBlockVisual3D);


            // It is also possible to show 3D text with using TextVisual3D.
            // This objects renders text with using 3D lines.
            // Its disadvantage is that it supports only an old style font that was used for plotters and cannot render all the characters.


            // TextBlockVisual3D renders the text with first rendering the text with the specified border to a texture.
            // This this texture is rendered into a plane 3D object.
            // This works very well when there are not a lot of texts.
            // But if many texts need to be rendered, then the it takes long to render all texts to textures and also they take a lot of memory.
            //
            // In this case the InstancedTextNode can be used because it only rendered individual characters and then reuses
            // the textures with rendered characters to show the texts. To make rendering even more efficient object instancing is used.
            //
            //
            // The first set in using the InstancedTextNode is to create its instance.
            //
            // There we define the FontFamily and FontWeight that will be the same for all added texts.
            //
            // We also define the size of the texture that will be used to render the characters.
            // It is recommended to use size that is power of 2 - for example 64, 128, 256, etc.
            // By default the fontBitmapSize is set to 128 that rendered characters to 128 x 128 texture.
            //
            // We can also set the useDynamicInstanceBuffer to true. This would create dynamic instance buffer.
            // This is recommended when the text data is changed very ofter (color, position or visibility is changed in each frame or similar).
            // Here we change data only occasionally, so preserve the useDynamicInstanceBuffer in its default value (this is better for GPU access to the buffer)
            _instancedTextNode = new InstancedTextNode(fontFamily: new FontFamily("Arial"),
                                                       fontWeight: FontWeights.Normal,
                                                       fontBitmapSize: 128,
                                                       useDynamicInstanceBuffer: false);


            // Than we can call AddText to add individual text to the InstancedTextNode.
            // Note that to be able to show text from the back side, we need to set hasBackSide to true (this rendered twice as many objects).
            // AddText method returns an instance of InstancedText object that can be used to change the color, position, show or hide text.
            _instancedText = _instancedTextNode.AddText("Ab3d.DXEngine", Colors.Orange, new Point3D(-190, 0, 0), size: 25, hasBackSide: true);

            // To change direction and orientation of text, we can call the SetTextDirection method.
            _instancedTextNode.SetTextDirection(textDirection: new Vector3D(1, 0, 0), upDirection: new Vector3D(0, 0, -1));

            // All characters from font are supported. Also new line is supported.
            _instancedTextNode.AddText("All chars:\n@üßščžç☯", Colors.Black, new Point3D(-100, 1, 50), size: 30, hasBackSide: true);


            _instancedTextNode.SetTextDirection(textDirection: new Vector3D(1, 0, 0), upDirection: new Vector3D(0, 1, 0));
            _instancedTextNode.AddText("Right->", Colors.Red, new Point3D(0, 30, 0), size: 30, hasBackSide: true);

            _instancedTextNode.SetTextDirection(textDirection: new Vector3D(0, 0, -1), upDirection: new Vector3D(0, 1, 0));
            _instancedTextNode.AddText("Forward->", Colors.Blue, new Point3D(0, 30, 0), size: 30, hasBackSide: true);

            _instancedTextNode.SetTextDirection(textDirection: new Vector3D(0, 1, 0), upDirection: new Vector3D(-1, 0, 0));
            _instancedTextNode.AddText("UP->", Colors.Green, new Point3D(0, 70, 0), size: 30, hasBackSide: true);


            // Sample on how to create text that is flipped on the back side (so it can be correctly read from the back side)
            var startPosition = new Point3D(10, 0, 0);

            _instancedTextNode.SetTextDirection(textDirection: new Vector3D(1, 0, 0), upDirection: new Vector3D(0, 1, 0));
            var flippedFrontFaceInstancedText = _instancedTextNode.AddText("FlippedBackSideText", Colors.Green, startPosition, size: 25, hasBackSide: false);

            // Based on size of previous text (instancedText.TextBounds), we can calculate the start position for the flipped back face text:
            var backFaceStartPosition = new Point3D(startPosition.X + flippedFrontFaceInstancedText.TextBounds.SizeX, startPosition.Y, startPosition.Z);

            _instancedTextNode.SetTextDirection(textDirection: new Vector3D(-1, 0, 0), upDirection: new Vector3D(0, 1, 0)); // flip textDirection, preserve upDirection
            var flippedBackFaceInstancedText = _instancedTextNode.AddText(flippedFrontFaceInstancedText.Text, flippedFrontFaceInstancedText.Color, backFaceStartPosition, size: 25, hasBackSide: false);


            // It is also possible to call AddText that takes transformation matrix instead of position and scale.
            // This method does not use current text direction that is set with SetTextDirection:

            var transform3DGroup = new Transform3DGroup();

            transform3DGroup.Children.Add(new ScaleTransform3D(20, 70, 20)); // Note that initially the font size is 1, so we need to scale it !!!
            transform3DGroup.Children.Add(new TranslateTransform3D(-120, -120, 0));

            _instancedTextNode.AddText("Custom transform", Colors.Gray, transform3DGroup.Value, hasBackSide: true);


            // If we want to immediately create character textures, we can call the InitializeResources method.
            // Note that MainDXViewportView.DXScene must not be null (this can be called in MainDXViewportView.DXSceneDeviceCreated or MainDXViewportView.DXSceneInitialized event handler)
            //_instancedTextNode.InitializeResources(MainDXViewportView.DXScene);


            // Show the InstancedTextNode as any other DXEngine's SceneNode:
            var sceneNodeVisual1 = new SceneNodeVisual3D(_instancedTextNode);

            MainViewport.Children.Add(sceneNodeVisual1);


            // To show text with other font or with other font weight, we need to create another InstancedTextNode
            _instancedTextNode2 = new InstancedTextNode(new FontFamily("Times New Roman"), FontWeights.Bold, fontBitmapSize: 128);
            _instancedTextNode2.AddText("Text with any font", Colors.Gold, new Point3D(100, -100, 0), 30, true);

            var sceneNodeVisual2 = new SceneNodeVisual3D(_instancedTextNode2);

            MainViewport.Children.Add(sceneNodeVisual2);


            SetupDemoSceneButtons(isDemoSceneShown: true);

            UpdateCharactersCountInfo();
        }
Exemple #4
0
        private void SceneTypeComboBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (!this.IsLoaded)
            {
                return;
            }


            MainViewport.Children.Clear();
            DisposeInstancedTextNodes();

            InfoTextBox.Text       = "";
            InfoTextBox.Visibility = Visibility.Collapsed;


            if (SceneTypeComboBox.SelectedIndex == 0)
            {
                CreateSimpleDemoScene();

                Camera1.Heading        = 30;
                Camera1.Attitude       = -20;
                Camera1.Distance       = 600;
                Camera1.TargetPosition = new Point3D(0, 0, 0);
            }
            else
            {
                _instancedTextNode = new InstancedTextNode(new FontFamily("Consolas"), FontWeights.Normal, fontBitmapSize: 128);

                // Reset direction
                _instancedTextNode.SetTextDirection(textDirection: new Vector3D(1, 0, 0), upDirection: new Vector3D(0, 1, 0));


                try
                {
                    Mouse.OverrideCursor = Cursors.Wait;

                    if (SceneTypeComboBox.SelectedIndex == 1)
                    {
                        CreateInstanceText(_instancedTextNode, centerPosition: new Point3D(0, 0, 0), size: new Size3D(1000, 500, 2000), xCount: 10, yCount: 20, zCount: 40, textColor: Colors.Black, textSize: 10);
                    }
                    else if (SceneTypeComboBox.SelectedIndex == 2)
                    {
                        CreateInstanceText(_instancedTextNode, centerPosition: new Point3D(0, 0, 0), size: new Size3D(2000, 2000, 2000), xCount: 20, yCount: 100, zCount: 100, textColor: Colors.Black, textSize: 10);
                    }
                    else if (SceneTypeComboBox.SelectedIndex == 3)
                    {
                        CreateInstanceText(_instancedTextNode, centerPosition: new Point3D(0, 0, 0), size: new Size3D(2000, 2000, 10000), xCount: 20, yCount: 100, zCount: 500, textColor: Colors.Black, textSize: 10);
                    }

                    var sceneNodeVisual1 = new SceneNodeVisual3D(_instancedTextNode);
                    MainViewport.Children.Add(sceneNodeVisual1);


                    Camera1.Heading        = -8.2881686066695;
                    Camera1.Attitude       = 3.35596244333162;
                    Camera1.Distance       = 1131.38948539394;
                    Camera1.TargetPosition = new Point3D(67.7795992281885, 14.1717311898692, 1.24683504967857);

                    UpdateCharactersCountInfo();
                }
                finally
                {
                    Mouse.OverrideCursor = null;
                }


                SetupDemoSceneButtons(isDemoSceneShown: false);
            }
        }