I did start writing a tute ages ago. Here's a snip.
Poly functions: It's not essential that all vertices are built before you start defining polys — just be sure that
the vertices you refer to exist. There are several flavours of this function: Poly3i builds triangles, Poly4i
quadrilaterals, and PolyBegin, Polyi and PolyEnd are used together to build polys with any number of
sides. They all take various combinations of the following parameters:
int sgn
determines which way the poly faces. This should be +1 or -1, though I suspect any value will work
and the sign will determine the result.
(what follows is the worst part of scripting a builder. You are warned that I may have got the signs
the wrong way round again!)
With sgn=1, the vertices are taken in an anti-clockwise direction when looking at the poly from the
exterior. When working out which order to take vertices, remember that Unreal uses a left-handed
co-ordinate system: looking down on the XY plane from the positive z-axis, x goes from left to right,
and y goes from bottom to top. Put another way, what I of as (0,1,0), Unreal sees as (0,-1,0). If
you're used to 3-D geometry the way it's taught in maths at school / university etc, prepare to be
thoroughly confused. As a last resort, list them in sequence, try building and if the poly is visible
from the wrong side, flip the value of sgn or re-order them.
As far as I can tell, the left-hand side of the poly's texture is lined up to the edge made by the first
two vertices in the list.
It's sometimes necessary to pass a variable or an expression here:
Example 1: if the spiral stairs are set to anticlockwise, we get a mirror image brush, so use a local
variable set to 1 or -1 depending on the value of the Anticlockwise parameter.
Example 2: brushes with a hollow option call the same function twice to build the sides. The
second call builds the inner cylinder/cone/thingy, and so the polys all need to face the other way.
Pass a value of +1 or -1 to the side builder function, which in turn passes sgn to the Poly call.
Example 3: caps for a cylinder are built with a nested Poly call. Use the variable from the control
loop, j say, to flip the cap poly. The native UEd builders use ( j = -1 , j < 2 , j+=2 ) and pass j; I
sometimes have j take 0, 1 and pass ( 2*j - 1 ) to the Poly call.
int Vertex
An integer value or expression, which specifies a vertex by build order. The first vertex you build is 0
and so on. In the examples below I'll use VertexA, VertexB etc to show different parameters of this
sort.
optional name ItemName
A variable of type name — the upshot is that it's a text string enclosed in ' rather than " and it can't be
set with an expression. For more on what it does and why the non-expression bit has driven me up
the wall, see the future development page. This parameter can be omitted.
optional PolyFlags
In a word, youch. The native sheet builder shows how to set these to produce two-sided sheet
polys but beyond that I have no idea. Omit this parameter to make regular polys; set to 0x00000108
for a two-sided sheet. Information on this would be gratefully received!
There are three different ways of defining a poly with the Poly functions:
Poly3i( sgn, VertexA , VertexB , VertexC , ItemName , PolyFlags ) ;
Poly4i( sgn, VertexA , VertexB , VertexC , VertexD , ItemName , PolyFlags ) ;
PolyBegin( sgn, ItemName , PolyFlags ) ;
Polyi( VertexA );
Polyi( VertexB );
Polyi( VertexC );
// and so on...
PolyEnd();
Poly3i and Poly4i define a 3-sided and 4-sided poly respectively, and it's these that are used the most
frequently. The others are used to define polys with a greater number of sides: PolyBegin starts a new
poly, Polyi adds a vertex to the poly's definition, and PolyEnd marks the end of a poly definition block. Note
that you can embed for loops within the PolyBegin...PolyEnd block.
I have no idea what happens if you put two PolyBegin with no PolyEnd in between, but I suspect it isn't
pretty.
Bear in mind that a poly must have at least 3 sides (in Euclidean space, that is!), and that the Unreal
engine currently has a maximum of 16 sides per poly — any larger and the poly will be split automatically;
this isn't a problem but the split lines can be non-regular and off-grid and look rather ugly.
There is also a function GetPolyCount(), which I assume returns the number of polys defined.