Click or drag to resize

Shapes

This page describes how shapes work in Grids 2.

What are shapes?

Shapes come in two varieties.

Implicit shapes

Implicit shapes are objects that can tell whether a point is inside the shape or not.

Classes that represent implicit shapes implement the IImplicit interface.

Explicit shapes

Explicit shapes are implicit shapes that also know their bounds, and can produce all the points inside it.

Classes that represent explicit shapes implement the IExplicit interface.

You can also see a shape as a set of points.

Where are shapes used in Grids 2?

You can do grid geometry using grid points and matrices without reference to any grid. But usually, game grids are finite, and some grid points are inside the grid, and some are not. We use grid shapes to handle this concept. When you construct a grid in code, you have to give the constructor an explicit shape. Behind the scenes this is used to allocate the memory for your cells.

Grids also implement the IExplicitShape interface; in this sense grids are explicit shapes – you can ask whether a point is inside the grid or not, you can get the bounds of your grid, and you can get a list of all points inside the grid. This means any algorithm that takes a shape can also take a grid, which is very useful for algorithm design.

How are bounds represented?

Bounds are represented through 3 types of object depending on whether the shape is 1D, 2D or 3D. For 1D, we use the GridInterval class. GridInterval represents a sequence of integers between two values. GridRect is just like Unity’s Rect class, but works with grid points instead of Vector2. It represents an axis-aligned rectangle in grid space. Similarly, GridBounds is like Unity’s Bounds object, but works with grid points instead of Vector3.

All three these objects are explicit shapes too, and this is useful to remember when designing algorithms. In particular, you can iterate over the points of a bounds object, which is neater than using nested loops and creating grid points on the fly.

How do I create shapes?

To create shapes in code, you can use the various static methods in ImplicitShape and ExplicitShape. Several primitive shapes are provided, and you can also use shape operations (described below) to manipulate shapes.

Explicit shapes can be created from implicit shapes if you specify the bounds using one of the following methods:

You can also create explicit shapes using a node editor. To do this, you need to create a 1D, 2D or 3D shape graph. The node editor allows you to create shape primitives, and manipulate them. Shape graphs can be added to mono behaviours, and this allows you to get hold of the shape. (This is how grid builders work). The node editor is described in more detail below.

What operations are supported on shapes?

Shapes (both implicit and explicit) support these operations:

Union

The resulting shape contains the points of all input shapes

Intersect

The resulting shape contains the points that are in all input shapes

Subtract

The resulting shape contains the points of one shape that are not in another

Product

The product operation that takes two input shapes, A and B, and a scaling vector (a grid point). All the points of A are scaled by this vector, and added to each point of B. The resulting set of points are the ones inside this new shape

These operations allow you to create new shapes from existing shapes.

How do I create a shape graph?

Creating a shape graph

  1. Right click in the Project Window where you want to save the shape graph. For a 2D shape, select Create | Grids | Shape Graph 2. For 1D, select Shape Graph 1 instead, or for 3D, select Shape Graph 3.

  2. Click on the shape graph, and click on the Edit button in the Inspector to edit the graph.

What does the shape node editor do exactly?

It allows you to build an explicit shape in the editor. You can do the same in code, but it is often easier to experiment to get the right shape in the editor. Grid builders use explicit shapes to construct grids, but you can also use them for other purposes.

To edit a shape graph, follow these steps:

  1. Add the nodes you need to make the shape you require, and set their fields to the correct values. To remove a node, click on the Remove button on the node. To remove all nodes, click the Clear button at the top of the node editor tool bar.

  2. Add one output node.

  3. Link them together, with the output node at the end of the sequence. To link the output of node A to the input of node B, click on the “Add link” button on node A, and click on node B. To remove a link, click on the red dot on the link.

  4. In complicated graphs, you may want to rename the nodes so it is easier to know what is going on. You can do this by clicking on the node name and typing a new name. (Since Grids 2.1)

  5. While tweaking the node graph, it may be useful to skip over a node temporarily. You can do this by clicking on the “Disable” button. This will make the node simply route its input to its output without processing. (Since Grids 2.1)

What does the Recompute button do?

It lets all nodes recompute and save values for internal use. This is specifically designed for nodes with a random element, to allow nodes to select new random values. (In general, you don’t want these to be recomputed every time the shape is accessed). Currently, all nodes are deterministic, so this feature is not used. We may introduce random nodes in the future, or you may want to add your own random nodes.

What do all the nodes do exactly?

Nodes come in several varieties.

Output Node

The output node marks the resulting shape of the graph.

Operator Node

Operator nodes take other shapes as inputs, and perform the operations described earlier. The Union and Intersection nodes can take any number of inputs, while the subtract and product nodes take two inputs each.

For 3D shapes, there are additional nodes (since Grids 2.2) that construct 3D shapes from 2D shapes.

See the Shape Operations article for details on shape operations.

Primitive Node

Primitive nodes describe basic shapes such as stars or parallelograms. See the Shape Index for a list of shapes supported by grids.

Can I make my own shape nodes?

Yes!

If your shape is primitive (it does not require other shapes as input), you can extend a new class from PrimitiveShapeNodeTPoint (where T is int, GridPoint2 or GridPoint3), and override the Generate method.

If you implement a shape operator, you can extend from AggregateShapeNodeTPoint, TInput, TOutput and override the Aggregate method.

In either case, you need to add the ShapeNodeAttribute to your class. It takes two parameters, a string and an integer. The first is a name. If you want to group the node with other nodes you can give it a name like this: “Group Name/Node Name”. The integer parameter denotes the number of dimensions of the shape, and should correspond to the type T referred to above.

Both the Generate and Aggregate methods simply needs to return a shape. To build a shape in code usually takes three steps:

  1. Make an implicit shape.

  2. Make a bounds object that will contain the shape.

  3. Call ToExplicit on the implicit shape and feed it the bounds.

  4. In some cases, you can work with explicit shapes directly. There are many functions that help with shape construction; explore the documentation of ExplicitShape and ImplicitShape.