Gavmacca
Topic Author
Posts: 6
Joined: 02 Jun 2025, 13:11

Starting with the basics with Blend, Noesis and Unreal

03 Jun 2025, 10:13

Hi there,

I am brand new to Noesis, I have the unreal samples and I have been reading the documentation but still struggling to understand some core principles.

I was wondering if anybody could help guide me through some absolute basics to develop a better understanding to help get me up on my feet with Noesis. I'm starting super simple.

Starting simple

Using Blend, I can create a new wpf project, Add some simple text and blue background:
<Window x:Class="TestProject.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TestProject"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800" Background="CadetBlue">
    <Grid>
        <TextBlock Text="Hello World" Foreground="DarkBlue" HorizontalAlignment="Left" VerticalAlignment="Top" FontSize="36"/>
    </Grid>
</Window>

Importing to Unreal
If I then import that into unreal, it does not render. However, looking at one of the samples, I saw that everything was wrapped using UserControl.

So I updated the above to then become this:
<UserControl x:Class="TestProject.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TestProject"
        mc:Ignorable="d"
        d:DesignWidth="1920"
        d:DesignHeight="1080"
        Background="LightBlue">
    <Grid>
        <TextBlock Text="Hello World" Foreground="DarkBlue" HorizontalAlignment="Left" VerticalAlignment="Top" FontSize="36"/>
    </Grid>
</UserControl>
This then renders in unreal when reimported.

Questions #1

I am just trying to understand the basics of why User Control renders but Window does not, am I right in assuming the reason it does not render inside Unreal is because Noesis within Unreal cannot use Window (as its not a WPF app) and instead it requires it to be a UserControl? Does this mean parent in my XAML always needs be a User Control? I tried looking through the documentation for something specific about this, but feel free to point me to it if I have missed it.

Code Behind Basics

Question #2
If I wanted to make MainWindow.cs file add the text to the grid (instead of defining the text up front in the XAML file), what would be the correct code within the .cs file for that to work? I have tried playing around with it, I can make it work fine with blend, but not with Noesis.

I have come across some examples with #if Noesis etc, but I think I just need a super basic example for adding content dynamically using the .cs file rather than having it existing in the XAML to begin with.

Ultimately my goal is to be able to read a csv file containing a dataset of 2d vectors, with this dataset I would then draw lines (using path geometry).


Text Blocks v Labels

Question #3

Should I not be using TextBlock? I read in the documentation about Label:
Label is a classic control that can be used to hold some text. Being a content control, it can hold arbitrary content in its Content property, but Label is really only useful for text.

Thanks for reading and I would appreciate any help to get me up on my feet! :)
 
User avatar
sfernandez
Site Admin
Posts: 3269
Joined: 22 Dec 2011, 19:20

Re: Starting with the basics with Blend, Noesis and Unreal

04 Jun 2025, 14:14

1. Window is a control that is not part of the Noesis core library, as it represents the operating system window and that is dependant on the integration (each engine - Unreal, Unity, custom - provides its own). For Unreal I recommend making your root element either a UserControl, Page or a simple panel like Grid as stated in the documentation (https://www.noesisengine.com/docs/Gui.C ... html#blend, see the Note in point 4).

By the way, if you used Window you should have seen an error message in the logs saying that Window is not supported.

2. C# code-behind is only used by the Blend project and it would be something like:
Grid grid = (Grid)FindName("LayoutRoot"); // assuming you put that name to the root Grid using x:Name
grid.Children.Add(new TextBlock());
This needs to be translated to a C++ class in the Unreal project (see UserControl sample included in the plugin zip):
Grid* grid = FindName<Grid>("LayoutRoot");
grid->GetChildren()->Add(MakePtr<TextBlock>());
Ultimately my goal is to be able to read a csv file containing a dataset of 2d vectors, with this dataset I would then draw lines (using path geometry).
You can generate a StreamGeometry and bind it to the Data property of a Path for this. Take a look at data binding here: https://www.noesisengine.com/docs/Gui.C ... ty-binding

3. You'll only need a Label in case you want to decorate the text with more things for your labels. In any other case TextBlock is the minimal and most efficient element to draw text in your UI.

Hope this helps.
 
Gavmacca
Topic Author
Posts: 6
Joined: 02 Jun 2025, 13:11

Re: Starting with the basics with Blend, Noesis and Unreal

04 Jun 2025, 14:29

Thank you very much!
 
Gavmacca
Topic Author
Posts: 6
Joined: 02 Jun 2025, 13:11

Re: Starting with the basics with Blend, Noesis and Unreal

05 Jun 2025, 13:05

I would be very grateful if any developers of Noesis could share their thoughts with regards to my use case:

What I am looking at achieving: rendering elements for a topographical map.

Very similar to what was achieved in OFP (I have recorded a video example below), this map system here was achieved back in 2001 and it was drawing many vector/geometric based paths, lines and shapes that were rendered in 2D, very fast and performant.

Examples
I have uploaded a video example here:
https://www.dropbox.com/scl/fi/hhc8g8dt ... 4qgar&dl=0

As you can see, there is many many contour lines, roads and also geometric shapes for forests and houses, you can zoom right in and see that the shapes aren't rasterized and instead vector/geometry based. Different contours appear based on zoom level, assets vanish if zooming out too far etc.

Here is another dynamic example where you can zoom about on an arma 3 map in the browser:
https://jetelain.github.io/Arma3Map/malden.html

Feedback
Do you believe Noesis within Unreal Engine would be suitable and hold up performance wise for consuming data and then drawing numerous geometry paths/shapes and then rendering it? Or would it not be suitable?

My main concern is with the sheer amount of data that would be consumed and then drawn, but then I think back to OFP and how it was achieved in 2001. However, if Noesis had all the datasets to consume, how do you feel it would get on?

Assuming I have these sorts of datasets to consume:
- Datasets for contours, each entry containing: An array of 2D vectors describing a single contour line
- Datasets for roads/paths, each entry containing: An array of 2D vectors describing a road/path
- Datasets for houses describing world loc, width/length of the shape to render etc.

Any thoughts or suggestions would be greatly appreciated!
 
User avatar
jsantos
Site Admin
Posts: 4402
Joined: 20 Jan 2012, 17:18
Contact:

Re: Starting with the basics with Blend, Noesis and Unreal

05 Jun 2025, 14:49

I recommend taking a look at the CustomRender sample included in the SDK. This is likely what you want to do for your project: implement the *OnRender* method on your side and decide what to render using the primitives offered by the *DrawingContext*.
 
Gavmacca
Topic Author
Posts: 6
Joined: 02 Jun 2025, 13:11

Re: Starting with the basics with Blend, Noesis and Unreal

05 Jun 2025, 15:41

I recommend taking a look at the CustomRender sample included in the SDK. This is likely what you want to do for your project: implement the *OnRender* method on your side and decide what to render using the primitives offered by the *DrawingContext*.
Thanks for the reply jsantos.

I assume this method is very similar in principle to the method offered in Unreal by Slate/UMG, OnPaint? (i.e. its essentially like a tick event?)

I was kind of hoping to do a one time function call that generates and adds the elements and I don't have to keep looping through the data each rendered frame and telling it to draw again in the exact same place?

I ask this because in WPF i can do something like this below which works fine as a single function call, it simply parses data from a file and then draws paths from it as a one time call:
foreach (string pathData in pathLines)
{
    if (string.IsNullOrWhiteSpace(pathData))
        continue;

    Geometry rawGeometry = Geometry.Parse(pathData.Trim());
    PathGeometry geometry = PathGeometry.CreateFromGeometry(rawGeometry);
    geometry.Transform = null;

    var path = new System.Windows.Shapes.Path
    {
        Stroke = Brushes.CadetBlue,
        StrokeThickness = 10,
        Data = geometry
    };

    DrawingCanvas.Children.Add(path);
}
I'm not having to put it in a 'OnPaint' like event (Though, I can understand WPF is likely doing that somewhere on it's own).

Also, as some general feedback on my use case, do you think it is within the scope of what Noesis is suited for / can handle ok? Or would the volume of geometry/paths that would need rendering for the paths, contours, and houses make it too heavy or impractical to handle effectively? Just trying to get an understanding whether you may look at this and think its too crazy or not, as its more assets to render than your typical UI.

Thanks again!
 
User avatar
jsantos
Site Admin
Posts: 4402
Joined: 20 Jan 2012, 17:18
Contact:

Re: Starting with the basics with Blend, Noesis and Unreal

06 Jun 2025, 14:47

I assume this method is very similar in principle to the method offered in Unreal by Slate/UMG, OnPaint? (i.e. its essentially like a tick event?)
Not exactly. In Noesis, the OnRender method is retained. If you don't invoke it again, the previous commands are reused for each frame.

The code you posted also works in Noesis. Which approach is better depends on several factors, such as the complexity and dynamic nature of the geometry.

You should probably try both approaches to see which works best for your use case.
 
Gavmacca
Topic Author
Posts: 6
Joined: 02 Jun 2025, 13:11

Re: Starting with the basics with Blend, Noesis and Unreal

12 Jun 2025, 14:46

I have been making great progress with Noesis with my use case, but I am running into an issue when zooming and I am also concerned about if I am going the right way about this. I would appreciate any input or feedback.

First the positives:

Extracting Contours
I run a function that samples my heightmap to generate contour lines. Each contour is stored as a unique JSON object with a list of 2D world-space points that define its path. The result is saved as a single JSON file, ready to be used with Noesis.

Sample JSON data
Here is a link to download my JSON path data for reference if needed:
https://www.dropbox.com/scl/fi/0sb6c88g ... qlxmr&dl=1

Result of Contour Generation in Unreal
Image

Translating to Noesis
I feed the JSON file to Unreal/Noesis, it loops through each object and constructs a path by reading the world pos of each point and adds it to my Canvas named MapDrawingCanvas. This does mean that the points are using world space coordinates on the UI (not sure if there is a better approach for this).

I can then view this as a map when i open the map in my Unreal level at runtime, I also have code setup so i can drag the map around (which translates the translate transform of the canvas) and I can zoom in and out (which scales the scale transform of the canvas)

Here is the result:
As you can see I have paths created for the contours from my data. Its heading in the right direction!
Image

XAML
My XAML is structured quite simply:
- User Control
--- Grid
------ Map Drawing Canvas
---------<Paths get added to Map Drawing Canvas>
<UserControl x:Class="Map.MainWindow"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             mc:Ignorable="d"
             d:DesignWidth="1920" d:DesignHeight="1080"
             MouseWheel="Window_MouseWheel"
             MouseDown="Window_MouseDown"
             MouseMove="Window_MouseMove"
             MouseUp="Window_MouseUp"
             Background="White">

    <Grid>
        <!-- Map Drawing Canvas - this where the map elements get added -->
        <Canvas x:Name="MapDrawingCanvas" Background="#FFD8D8D8">
            <Canvas.RenderTransform>
                <TransformGroup>
                    <ScaleTransform x:Name="CanvasScaleTransform" ScaleX="1" ScaleY="1" />
                    <TranslateTransform x:Name="CanvasTranslateTransform" X="0" Y="0" />
                </TransformGroup>
            </Canvas.RenderTransform>
        </Canvas>
    </Grid>
</UserControl>
---------

Issue: Zooming and keeping Stroke Thickness Consistent
The paths initially render fine at a thickness of 1.0, no issues or errors in the log file. If I zoom in and out with the mouse wheel (scaling the map drawing canvas), it works fine, no issues.

However, I would like to make the stroke thickness consistent regardless of zoom level, i.e. if i zoom out, it doesn't become too thin (you can see a bit of this appearing in the screenshot above), or if i zoom in, it doesn't become too thick.

My current approach is: Adjust the stroke thickness of the paths when I zoom in/out.

The problem is: When I zoom in and set the thickness to anything thin (below 3.0), I get a hitch and this warning:
LogNoesis: Warning: Path too complex to render. Please split the geometry into several paths.
This occurs even with applying the stroke thickness to one path. Anything over this thickness value and there seems to be no issue.
With them being contour lines I do need them to be quite thin...I have also tried what it suggests, splitting them into several paths per contour but its not overly helped, though i'm not sure how much they need to be split.

Any suggestions on this issue? Am I going about this the wrong way?

For reference, here is the relevant bit of code that executes when I zoom (It might not be the best way of doing it):
float ContourComputedThickness = FMath::Clamp((ContourOriginalThickness / EffectiveZoom), ContourMinThickness, ContourMaxThickness);

        const auto& MapChildren = MapDrawingCanvas->GetChildren();

        for (int32 i = 0; i < MapChildren->Count(); ++i)
        {
            Noesis::UIElement* Child = MapChildren->Get(i);

            if (Noesis::Path* PathShape = Noesis::DynamicCast<Noesis::Path*>(Child))
            {
               PathShape->SetStrokeThickness(ContourComputedThickness);
            }
        }
Thanks for reading!
 
User avatar
jsantos
Site Admin
Posts: 4402
Joined: 20 Jan 2012, 17:18
Contact:

Re: Starting with the basics with Blend, Noesis and Unreal

13 Jun 2025, 12:23

Congratulations on the progress you're making!
Any suggestions on this issue? Am I going about this the wrong way?
There’s nothing wrong on your side. You're simply encountering some inherent limitations in our architecture, decisions we made to prioritize performance in other scenarios.
However, I would like to make the stroke thickness consistent regardless of zoom level, i.e. if i zoom out, it doesn't become too thin (you can see a bit of this appearing in the screenshot above), or if i zoom in, it doesn't become too thick.
While I don’t have a straightforward solution for this at the moment, it’s important to note that adjusting stroke thickness in Noesis requires regenerating the geometry. Since this is currently handled on the CPU (we have long-term plans to move this to the GPU), doing so per frame, especially with complex paths, can have a significant performance impact. A potential workaround could be to update geometry incrementally over multiple frames, though this will depend on your use case.

Additionally, our renderer does not currently support a dedicated path for ultra-thin (hairline) strokes.
LogNoesis: Warning: Path too complex to render. Please split the geometry into several paths.
Internally, we upload GPU geometry using 16-bit indices. This brings substantial performance benefits compared to 32-bit indices, particularly because we re-upload geometry every frame, Noesis is optimized for scenarios with constant animation. In our design, predictable and stable performance takes precedence over peak speed in static scenes.

To resolve this warning, try simplifying your paths by reducing the number of points (lines, quads, cubics) or splitting them into smaller segments. This should eliminate the error.
 
Gavmacca
Topic Author
Posts: 6
Joined: 02 Jun 2025, 13:11

Re: Starting with the basics with Blend, Noesis and Unreal

13 Jun 2025, 14:27

Congratulations on the progress you're making!
Any suggestions on this issue? Am I going about this the wrong way?
There’s nothing wrong on your side. You're simply encountering some inherent limitations in our architecture, decisions we made to prioritize performance in other scenarios.
However, I would like to make the stroke thickness consistent regardless of zoom level, i.e. if i zoom out, it doesn't become too thin (you can see a bit of this appearing in the screenshot above), or if i zoom in, it doesn't become too thick.
While I don’t have a straightforward solution for this at the moment, it’s important to note that adjusting stroke thickness in Noesis requires regenerating the geometry. Since this is currently handled on the CPU (we have long-term plans to move this to the GPU), doing so per frame, especially with complex paths, can have a significant performance impact. A potential workaround could be to update geometry incrementally over multiple frames, though this will depend on your use case.

Additionally, our renderer does not currently support a dedicated path for ultra-thin (hairline) strokes.
LogNoesis: Warning: Path too complex to render. Please split the geometry into several paths.
Internally, we upload GPU geometry using 16-bit indices. This brings substantial performance benefits compared to 32-bit indices, particularly because we re-upload geometry every frame, Noesis is optimized for scenarios with constant animation. In our design, predictable and stable performance takes precedence over peak speed in static scenes.

To resolve this warning, try simplifying your paths by reducing the number of points (lines, quads, cubics) or splitting them into smaller segments. This should eliminate the error.

Thanks jsantos, I may try approach it in a completely different way to try work around this.

Fixed Zoom Levels + Contour Render Layers

One way I can think of is: having fixed zoom levels for the map that i toggle between when i roll the mouse wheel. Each zoom level having its own canvas (if it warrants it) that contains the path data in it at a different thickness level.

Then when i switch zoom level, instead of adjusting stroke length, I simply switch the active contour canvas for the desired zoom level, the rest would be collapsed.

This way I avoid having iterate through every path and update stroke thickness when I execute the zoom. Not sure if i'm going to run into issues with this approach or if its even a better solution at this stage, but i will investigate.

Better Contours

I have made good progress with getting better contour data from my landscape heightmap, here is my result from my function that captures the data - though this is currently rendered from my blend project, I am going to be translating it to Noesis shortly:

Image

Who is online

Users browsing this forum: Ahrefs [Bot] and 2 guests