The primary goals of this assignment are:
- Create a UE4 Plugin.
- Extend the Blueprint system.
- Create and use a blue noise point distribution
For this assignment, you'll be creating a new Blueprint node and data type in a UE4 plugin. In this case, we'll create a new Blueprint type to hold data about a blue noise point distribution generated using Mitchell's best candidate algorithm. You'll also create a Blueprint node to provide a random number seed to an object of this new type, and one to return a point location from it, and a simple Blueprint script to place some objects using this blue noise point distribution.
Objects distributed using true random numbers will tend to be clumpy because each position is independent of all of the ones before, so has no memory that another object has been placed nearby or that there is an unfilled gap. A blue noise distribution spaces has correlation between the point placements to make them more even in density, To summarize Mitchell's algorithm, you first place one point at a random x/y location. At each step, select several candidate points and keep the one furthest from any already placed points. You should use distance calculations that wrap around from left to right and top to bottom so the distribution will tile and to avoid preference for point locations along the edges.
The linked page suggests choosing a set of candidate points at each iteration proportional to the number of points placed so far. If you naively loop through all of the already placed points to find the distances for each candidate, the resulting algorithm to generate N points will run in O(N3) time
|Randomly distributed objects||Blue-noise distributed objects|
For this assignment, I've gone a bit more general with the steps, though I have given some pointers for where to find examples of code similar to what you will need to write.
Create a project
- Create a Basic Code C++ project (with no starter content) called
assn4, and a level called "
assn4" set as your default editor level.
- As usual, put the project at the top level of your git repository
Create a Blueprint test case
- Create a Blueprint actor to spawn models with random positions and rotations within a square.
- Your Blueprint should have four variables: an integer random seed, a number of elements to spawn, and two hidden RandomStream variables (one for positions and one for rotation).
- When you create a variable, you can change its type (and allowable range and other attributes) in the panel on the right
- Click the closed eye icon next to the variable name in the variable list to make it visible in the editor details window. Otherwise, it is considered a hidden local variable.
- The screenshot below shows a working Construction script actor Blueprint to do the random placement. Recreate this Blueprint or something similar.
- Initialize the random stream for position given the seed.
- Add an InstancedStaticMeshComponent
- In the detail panel for this node, you can choose any static mesh and material you want, either one already available or by making something new
- Loop for the number of elements
- On each iteration, create a transform using the position random stream for X/Y, and the rotation random stream for orientation.
- Use AddInstance to add a copy at that location
- Random numbers can be clumpy and pack objects too closely. This is why it is common to use something like a blue noise distribution for placement of things like trees or vegetation.
Create a Blueprint plugin
- In Settings > Plugins, create a new Blueprint plugin
- Once loaded, you can recompile and hot-reload from Windows > Developer > Modules > (find your plugin in the list) > Recompile
- The editor toolbar "Compile" button only does "game" code (actors and components), not plugins
Create Blueprint nodes and data
- Make a Blueprint type to hold a random stream object and set of generated 2D point locations
- Look for things tagged
USTRUCT(BlueprintType)for examples of Blueprint-accessible types
KismetMathLibraryhas some of the simpler examples.
- Look for things tagged
- Make Blueprint node to initialize that type from a random seed, and another to return a single point
- Look at how the
RandomStreamblueprint nodes work.
- To get something working and testable quickly, you can just return a random position (equivalent to the first Blueprint) before you do the full blue noise algorithm.
- Look at how the
Blueprint test case
- Make a copy of your existing Blueprint test class
- Modify it to use your new blue noise type instead of RandomStream for the position.
- This should look similar to the image below
Mitchell's Best-candidate Algorithm
- Implement Mitchell's best-candidate algorithm in your Blueprint node.
- If N points have been generated so far, your node should try 5N candidate points, and return the one farthest from any already placed point.
For up to 10 points of extra credit, only available if you submit by the original due date, use some data structure to make the point distance queries faster (for the base version of the assignment, you can just do a linear search through all of the already-placed points). A few options include a uniform grid (with re-binning as the number of points grows), a quad tree, a K-D tree, or a BSP tree.
For full credit, you must commit multiple times during your development.
assn4.txt. Tell us what works and what doesn't, and anything else you think we should know for grading. Include a couple of screen shots showing different numbers of spawned objects with both the random and blue noise distributions.
Make sure your
assn4.txt file tells us if you attempted the extra credit, and if so, includes a description of the data structure you decided to use and your source(s) of information on it.
Push to your repository, and tag your final commit with an