Alex McGilvray

LevelViz 004 : First version now available, creating a plugin and making a new UI

May 3rd, 2016

I’ve now hit a major milestone for LevelViz. All the general features I wanted at conception are now implemented. There’s still a lot that can be done though. Mobile support will need some work for the plan view due to platform support of post-processes. The tools could use a second pass and be cleaned up. Finally the UI can always benefit from a little more time and love 🙂

Here is a video showing how to author a new ArchViz scene followed by a demonstration of the resulting built application.

Conversion to plugin and Github source

Until recently I have been developing LevelViz as a standard Unreal project which means it can’t really be used in any other projects easily. I spent about half a day converting the project to a plugin so that it can be used as intended. Implementing plugins for different engines and frameworks can sometimes be quite difficult or frustrating. I’m happy to say that overall the process is quite easy with Unreal. If you’ve already been properly setting up your code modules then you have actually already done most of the work.

The plugin source is now on github. There are some UI assets that are recommended to use with the plugin which I don’t have on the repository yet. I’m still undecided on whether I will distribute them similar to how Epic does with the Unreal engine in a separate download or if I will update the github repo to contain an entire driver project. In the coming weeks I will have my solution up. If anyone is attempting to use the plugin in the meantime and needs the assets they can email me directly and I can either send them or prioritize getting the assets up on source control.

The github repo can be found here : https://github.com/AlexMcGilvray/LevelViz

New UI

As you might notice I also did a complete redo of the UI. The previous version use render targets to display thumbnails of the connected vantage points you could transition to. It seemed like it would work in my head but the reality is the render targets are so small on the screen that they are too hard to read. There is also a fairly significant performance issue with having so many render targets.

Instead of using the render targets I decided to author some UI icons which I would place on the screen roughly where the next vantage point is (done using some world to screen coordinate conversions). This method works quite well but doesn’t work for the case where a connected vantage point is not visible because it’s outside of the cameras frustum. Projecting from world to screen coordinates for objects not visible in the cameras frustum is not a good idea so I made a bit of a custom solution to deal with vantage points that aren’t in view.

Here is the old UI

oldui

In a nutshell what I do in the UI is any offscreen vantage point uses the standard vantage point UI element with an arrow attached that points roughly in the direction of the vantage point. I say roughly because the arrow is pointing on the UI flat 2d coordinate space at an object in 3d space.

newui

To do this I do a series of steps. First for each vantage point, I test to see if it’s within the cameras frustrum, if it’s not in the frustrum then I continue to the next step. At this point I consider the current vantage point the center of a clock where it’s direction on the XY axis is 12 oclock. From here I take the target vantage point and calculate a direction vector relative to the current vantage point. Finally I rotate the resulting direction so it’s relative to the source vantage points orientation.

	
FVector2D UHelperBlueprints::GetClockRotationOfActorRelativeToOtherActor(AActor * const TargetActor, AActor * const Source)
{
   FVector TargetLocation = TargetActor->GetActorLocation();
   FVector SourceLocation = Source->GetActorLocation();
   FVector FinalDirection = SourceLocation - TargetLocation;
   FVector SourceForward = Source->GetActorForwardVector();
   FinalDirection.Normalize();
   FinalDirection = FinalDirection.RotateAngleAxis(FMath::RadiansToDegrees(FMath::Atan2(SourceForward.X, SourceForward.Y)), FVector(0, 0, 1));
   return FVector2D(FinalDirection.X, FinalDirection.Y);
}

Now the reason I did it this way is ultimately I’m projecting this vector onto the UI facing the correct direction. Imagine you are looking down on the actor in question from a birds eye view where the actors forward direction vector is always north and we then draw an arrow from that actor to the vantage point in question. We then project this onto the UI and have an arrow that roughly points at the offscreen vantage point.

Of course this is just a direction vector at this point. We need to scale it so that it gets close to the edge of the screen without being cutoff. I did most of this math logic in blueprints which I think might have been a bit of a mistake. The initial iteration and setup was nice but the constant re-wiring as I iterated was pretty tedious and slower compared to writing code. Going forward I plan to do any sizable math formulas in code then expose them as blueprint nodes. Essentially if I’m doing lots of basic arithmetic in blueprints then that chunk of logic is a good candidate to be done in code.