# Generate Plane

## Summary

Below is an example demonstrating the use of the geometry pipeline to generate a geometric plane.

## Example

Generate_Plane.dsa
```// Define an anonymous function;
// serves as our main loop,
// limits the scope of variables
(function(){

/*********************************************************************/
// Number : A function to convert from meters/yards/feet/inches to centimeters
function convertToCM( nVal, sFromUnit )
{
switch( sFromUnit.lower() ){
case "m":
return nVal * 100;
case "yd":
return nVal * 36.0 * 2.54;
case "ft":
return nVal * 12.0 * 2.54;
case "in":
return nVal * 2.54;
}

return nVal;
};

/*********************************************************************/
// String : A function for finding a unique label in the scene
function getUniqueLabel( sLabel )
{
// Initialize
var sUnqLabel = sLabel;
// If a node by the same label already exists
if( Scene.findNodeByLabel( sUnqLabel ) ){
// Create an array of the label parts
var aLabel = sUnqLabel.split( " " );
// Initialize
var sPreLabel = sUnqLabel;
// Get the last label part
var sLastPart = aLabel[ aLabel.length - 1 ];
// If the last label part is a number enclosed in parens
if( sLastPart.startsWith( "(" ) && sLastPart.endsWith( ")" ) &&
!isNaN( sLastPart.substring( 1, sLastPart.length - 1 ) ) ){
// Get rid of the number
aLabel.pop();
// Reconstruct the Label without the number
sPreLabel = aLabel.join( " " );
}
// Initialize a count
var i = 2;
// Until we cannot find a node with the label
while( Scene.findNodeByLabel( String( "%1 (%2)" ).arg( sPreLabel ).arg( i ) ) ){
// Increment the count
i += 1;
}
// Construct the unique Label
sUnqLabel = String( "%1 (%2)" ).arg( sPreLabel ).arg( i );
}

// Return the unique Label
return sUnqLabel;
};

/*********************************************************************/
// Get the user input
var sOrigin = "Object Center"; // "World Center"
var nSize = 10;
var sUnit = "cm"; // "m", "yd", "ft", "in"
var nDivisions = 10;

// Convert the input value to centimeters
nSize = convertToCM( nSize, sUnit );

// Sanity check the input values
if ( nSize <= 0.0 || nDivisions < 1 )
{
// We are done...
return;
}

// Let the user know we are busy
setBusyCursor();

// Create new node
var oNode = new DzNode();

// Set the node name;
// use a name that is consistent with the create primitive action
oNode.setName( "Plane" );

// Build the label of the node
var sLabel = String( "Plane %1x%2 %3%4" )
.arg( nDivisions )
.arg( nDivisions )
.arg( nSize )
.arg( sUnit );
oNode.setLabel( getUniqueLabel( sLabel ) );

// Create a new object
var oObject = new DzObject();

// Set the object name;
// use a name that is consistent with the create primitive action
oObject.name = String( "pPlane(%1)%2" ).arg( nSize ).arg( nDivisions );

// Create a new polygonal shape
var oFacetShape = new DzFacetShape();

// Set the shape name and label;
// use a name that is consistent with the create primitive action
oFacetShape.name = "Default";
oFacetShape.setLabel( oFacetShape.name );

// Create a new polygonal mesh
var oFacetMesh = new DzFacetMesh();

// Create a new default material
var oMaterial = new DzDefaultMaterial();

// Set the material name and label;
// use a name that is consistent with the create primitive action
oMaterial.name = "Default";
oMaterial.setLabel( oMaterial.name );

// Add the material to the shape

// Begin editing the mesh
oFacetMesh.beginEdit();

// Get the UV map
var oMap = oFacetMesh.getUVs();

// Activate the material; all new geometry will be added to this
oFacetMesh.activateMaterial( oMaterial.name );

// Declare some variables for generating the mesh
var i, j, idx, numVerts = nDivisions + 1;
var x, z, nHalfSize = nSize / 2;
var vecUVs = new DzVec3( 0, 0, 0 );

// Pre-size the vertex array; faster than dynamic resizing
oFacetMesh.preSizeVertexArray( numVerts * numVerts );

// Create the vertices/uvs
for( i = 0; i < numVerts; i += 1 ){
z = i / nDivisions;
vecUVs.y = z;
for( j = 0; j < numVerts; j += 1 ){
x = j / nDivisions;
vecUVs.x = x;
oFacetMesh.addVertex( x * nSize - nHalfSize, 0, nHalfSize - z * nSize );
oMap.appendPnt2Vec( vecUVs );
}
}

// Pre-size the facet array; faster than dynamic resizing
oFacetMesh.preSizeFacets( nDivisions * nDivisions );

var aVertexIndices = new Array( 4 );

// Create the faces
for( i = 0; i < nDivisions; i += 1 ){
for( j = 0; j < nDivisions; j += 1 ){
aVertexIndices[0] = j + (i * numVerts);
aVertexIndices[1] = j + (i * numVerts) + 1;
aVertexIndices[2] = j + ((i + 1) * numVerts) + 1;
aVertexIndices[3] = j + ((i + 1) * numVerts);

}
}

// Finish editing the mesh
oFacetMesh.finishEdit();

// Set the mesh for the shape
oFacetShape.setFacetMesh( oFacetMesh );

// Add the shape to the object

// Add the object to the node
oNode.setObject( oObject );

// Get the local bounding box
var boxLocal = oNode.getLocalBoundingBox();
var vecMax = boxLocal.max;
var vecMin = boxLocal.min;

// If the user chose the object center for the origin
if( sOrigin == "Object Center" ){
// Get the middle of the height of the box
var nMid = (vecMax.y + vecMin.y) * 0.5;

// Set the origin; default and current
var vecOrigin = new DzVec3(0, nMid, 0);
oNode.setOrigin( vecOrigin, true );
oNode.setOrigin( vecOrigin );
}

// If the height of the bounding box is less than
// 1 unit (1cm) tall, set it to be 1 unit tall
if( vecMax.y < 1 ){
vecMax.y = 1;
}

// Set the end point; default and current
var vecEndPoint = new DzVec3( 0, vecMax.y, 0 );
oNode.setEndPoint( vecEndPoint, true );
oNode.setEndPoint( vecEndPoint );

// Get the presentation for the node
var oPresentation = oNode.getPresentation();

// If the node did not have a presentation,
// create one and assign it to the node
if( !oPresentation ){
oPresentation = new DzPresentation();
oNode.setPresentation( oPresentation );
}

// Set the type of node
oPresentation.type = "Prop";

// Add the node to the scene