Skip to content
This repository has been archived by the owner on Feb 11, 2024. It is now read-only.

Additional Features for Curved Staircase Compound Brushes #30

Merged
merged 4 commits into from
Jan 30, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
266 changes: 211 additions & 55 deletions Scripts/Brushes/CompoundBrushes/CurvedStairBrush.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,22 @@ public class CurvedStairBrush : CompoundBrush
[SerializeField]
bool counterClockwise = false;

/// <summary>Whether the stairs reach down to the bottom.</summary>
[SerializeField]
bool fillToBottom = true;

/// <summary>Whether to generate stairs or a curved wall.</summary>
[SerializeField]
bool curvedWall = false;

/// <summary>Whether the floor is stairs or a smooth slope.</summary>
[SerializeField]
bool slopedFloor = false;

/// <summary>Whether the ceiling is stairs or a smooth slope.</summary>
[SerializeField]
bool slopedCeiling = false;

/// <summary>The last known extents of the compound brush to detect user resizing the bounds.</summary>
private Vector3 m_LastKnownExtents;
/// <summary>The last known position of the compound brush to prevent movement on resizing the bounds.</summary>
Expand Down Expand Up @@ -102,7 +118,6 @@ public override void Invalidate (bool polygonsChanged)

// local variables
List<Vector3> vertexPositions = new List<Vector3>();
Plane plane;
Vector3 rotateStep = new Vector3();
Vector3 vertex = new Vector3(), newVertex = new Vector3();
float adjustment;
Expand All @@ -128,7 +143,10 @@ public override void Invalidate (bool polygonsChanged)

newVertex = Quaternion.Euler(rotateStep * x) * vertex;
vertexPositions.Add(new Vector3(newVertex.x, vertex.z - adjustment, newVertex.y));
vertex.z += stepHeight;
if (curvedWall)
vertex.z = stepHeight * numSteps;
else
vertex.z += stepHeight;
vertexPositions.Add(new Vector3(newVertex.x, vertex.z, newVertex.y));
}

Expand All @@ -145,7 +163,10 @@ public override void Invalidate (bool polygonsChanged)

newVertex = Quaternion.Euler(rotateStep * x) * vertex;
vertexPositions.Add(new Vector3(newVertex.x, vertex.z - adjustment, newVertex.y));
vertex.z += stepHeight;
if (curvedWall)
vertex.z = stepHeight * numSteps;
else
vertex.z += stepHeight;
vertexPositions.Add(new Vector3(newVertex.x, vertex.z, newVertex.y));
}

Expand Down Expand Up @@ -183,6 +204,14 @@ public override void Invalidate (bool polygonsChanged)
index3 = 3;
}

// we force NoCSG mode if special NoCSG operators are used.
if (curvedWall) { slopedFloor = false; slopedCeiling = false; }
if (fillToBottom) { slopedCeiling = false; }
if (slopedFloor || slopedCeiling)
{
this.IsNoCSG = true;
}

// we calculate the bounds of the output csg.
Bounds csgBounds = new Bounds();

Expand All @@ -207,109 +236,219 @@ public override void Invalidate (bool polygonsChanged)
// | Back | Left | Right | Front | Bottom | Top |
// +--------+--------+--------+--------+--------+--------+



// retrieve the vertices of the top polygon.
Vertex[] vertices = polygons[5].Vertices;

// step top.
vertices[index0].Position = vertexPositions[outerStart + (i * 2) + 2];
vertices[index1].Position = vertexPositions[outerStart + (i * 2) + 1];
vertices[index2].Position = vertexPositions[innerStart + (i * 2) + 1];
vertices[index3].Position = vertexPositions[innerStart + (i * 2) + 2];
if (slopedFloor)
{
// create a smooth slope.
vertices[index0].Position = vertexPositions[outerStart + (i * 2) + 2 + 1];
vertices[index1].Position = vertexPositions[outerStart + (i * 2) + 1];
vertices[index2].Position = vertexPositions[innerStart + (i * 2) + 1];
vertices[index3].Position = vertexPositions[innerStart + (i * 2) + 2 + 1];
}
else
{
// create blocky stairs.
vertices[index0].Position = vertexPositions[outerStart + (i * 2) + 2];
vertices[index1].Position = vertexPositions[outerStart + (i * 2) + 1];
vertices[index2].Position = vertexPositions[innerStart + (i * 2) + 1];
vertices[index3].Position = vertexPositions[innerStart + (i * 2) + 2];
}

// calculate a normal using a virtual plane.
GenerateNormals(polygons[5]);

// update uv coordinates to prevent distortions using barnaby's genius utilities.
vertices[index0].UV = GeometryHelper.GetUVForPosition(polygons[5], vertexPositions[outerStart + (i * 2) + 2]);
vertices[index1].UV = GeometryHelper.GetUVForPosition(polygons[5], vertexPositions[outerStart + (i * 2) + 1]);
vertices[index2].UV = GeometryHelper.GetUVForPosition(polygons[5], vertexPositions[innerStart + (i * 2) + 1]);
vertices[index3].UV = GeometryHelper.GetUVForPosition(polygons[5], vertexPositions[innerStart + (i * 2) + 2]);
GenerateUvCoordinates(polygons[5]);



// retrieve the vertices of the front polygon.
vertices = polygons[3].Vertices;

// step front.
vertices[index0].Position = vertexPositions[outerStart + (i * 2) + 1];
vertices[index1].Position = vertexPositions[bottomOuterStart + i];
vertices[index2].Position = vertexPositions[bottomInnerStart + i];
vertices[index3].Position = vertexPositions[innerStart + (i * 2) + 1];
if (fillToBottom)
{
// fill downwards to the bottom.
vertices[index0].Position = vertexPositions[outerStart + (i * 2) + 1];
vertices[index1].Position = vertexPositions[bottomOuterStart + i];
vertices[index2].Position = vertexPositions[bottomInnerStart + i];
vertices[index3].Position = vertexPositions[innerStart + (i * 2) + 1];
}
else
{
// fill downwards to the step height.
vertices[index0].Position = vertexPositions[outerStart + (i * 2) + 1];
vertices[index1].Position = vertexPositions[outerStart + (i * 2) + 1] - new Vector3(0.0f, stepHeight, 0.0f);
vertices[index2].Position = vertexPositions[innerStart + (i * 2) + 1] - new Vector3(0.0f, stepHeight, 0.0f);
vertices[index3].Position = vertexPositions[innerStart + (i * 2) + 1];
}
if (slopedCeiling)
{
// create a smooth ceiling slope.
vertices[index1].Position -= new Vector3(0.0f, stepHeight, 0.0f);
vertices[index2].Position -= new Vector3(0.0f, stepHeight, 0.0f);
}

// calculate a normal using a virtual plane.
plane = new Plane(vertices[index1].Position, vertices[index2].Position, vertices[index3].Position);
vertices[index0].Normal = plane.normal;
vertices[index1].Normal = plane.normal;
vertices[index2].Normal = plane.normal;
vertices[index3].Normal = plane.normal;
GenerateNormals(polygons[3]);

// update uv coordinates to prevent distortions using barnaby's genius utilities.
GenerateUvCoordinates(polygons[3]);



// retrieve the vertices of the left polygon.
vertices = polygons[1].Vertices;

// inner curve.
vertices[index0].Position = vertexPositions[bottomInnerStart + i + 1];
vertices[index1].Position = vertexPositions[innerStart + (i * 2) + 2];
vertices[index2].Position = vertexPositions[innerStart + (i * 2) + 1];
vertices[index3].Position = vertexPositions[bottomInnerStart + i];
if (fillToBottom)
{
// fill downwards to the bottom.
vertices[index0].Position = vertexPositions[bottomInnerStart + i + 1];
vertices[index1].Position = vertexPositions[innerStart + (i * 2) + 2];
vertices[index2].Position = vertexPositions[innerStart + (i * 2) + 1];
vertices[index3].Position = vertexPositions[bottomInnerStart + i];
}
else
{
// fill downwards to the step height.
vertices[index0].Position = vertexPositions[innerStart + (i * 2) + 2] - new Vector3(0.0f, stepHeight, 0.0f);
vertices[index1].Position = vertexPositions[innerStart + (i * 2) + 2];
vertices[index2].Position = vertexPositions[innerStart + (i * 2) + 1];
vertices[index3].Position = vertexPositions[innerStart + (i * 2) + 1] - new Vector3(0.0f, stepHeight, 0.0f);
}
if (slopedFloor)
{
// create a smooth floor slope.
vertices[index1].Position = vertexPositions[innerStart + (i * 2) + 2 + 1];
}
if (slopedCeiling)
{
// create a smooth ceiling slope.
vertices[index3].Position = vertexPositions[innerStart + (i * 2) + 1] - new Vector3(0.0f, stepHeight * 2.0f, 0.0f);
}

// calculate a normal using a virtual plane.
plane = new Plane(vertices[index1].Position, vertices[index2].Position, vertices[index3].Position);
vertices[index0].Normal = plane.normal;
vertices[index1].Normal = plane.normal;
vertices[index2].Normal = plane.normal;
vertices[index3].Normal = plane.normal;
GenerateNormals(polygons[1]);

// update uv coordinates to prevent distortions using barnaby's genius utilities.
GenerateUvCoordinates(polygons[1]);



// retrieve the vertices of the right polygon.
vertices = polygons[2].Vertices;

// outer curve.
vertices[index0].Position = vertexPositions[outerStart + (i * 2) + 2];
vertices[index1].Position = vertexPositions[bottomOuterStart + i + 1];
vertices[index2].Position = vertexPositions[bottomOuterStart + i];
vertices[index3].Position = vertexPositions[outerStart + (i * 2) + 1];
if (fillToBottom)
{
// fill downwards to the bottom.
vertices[index0].Position = vertexPositions[outerStart + (i * 2) + 2];
vertices[index1].Position = vertexPositions[bottomOuterStart + i + 1];
vertices[index2].Position = vertexPositions[bottomOuterStart + i];
vertices[index3].Position = vertexPositions[outerStart + (i * 2) + 1];
}
else
{
// fill downwards to the step height.
vertices[index0].Position = vertexPositions[outerStart + (i * 2) + 2];
vertices[index1].Position = vertexPositions[outerStart + (i * 2) + 2] - new Vector3(0.0f, stepHeight, 0.0f);
vertices[index2].Position = vertexPositions[outerStart + (i * 2) + 1] - new Vector3(0.0f, stepHeight, 0.0f);
vertices[index3].Position = vertexPositions[outerStart + (i * 2) + 1];
}
if (slopedFloor)
{
// create a smooth floor slope.
vertices[index0].Position = vertexPositions[outerStart + (i * 2) + 2 + 1];
}
if (slopedCeiling)
{
// create a smooth ceiling slope.
vertices[index2].Position = vertexPositions[outerStart + (i * 2) + 1] - new Vector3(0.0f, stepHeight * 2.0f, 0.0f);
}

// calculate a normal using a virtual plane.
plane = new Plane(vertices[index1].Position, vertices[index2].Position, vertices[index3].Position);
vertices[index0].Normal = plane.normal;
vertices[index1].Normal = plane.normal;
vertices[index2].Normal = plane.normal;
vertices[index3].Normal = plane.normal;
GenerateNormals(polygons[2]);

// update uv coordinates to prevent distortions using barnaby's genius utilities.
GenerateUvCoordinates(polygons[2]);



// retrieve the vertices of the bottom polygon.
vertices = polygons[4].Vertices;

// bottom.
vertices[index0].Position = vertexPositions[bottomOuterStart + i];
vertices[index1].Position = vertexPositions[bottomOuterStart + i + 1];
vertices[index2].Position = vertexPositions[bottomInnerStart + i + 1];
vertices[index3].Position = vertexPositions[bottomInnerStart + i];
if (fillToBottom)
{
// fill downwards to the bottom.
vertices[index0].Position = vertexPositions[bottomOuterStart + i];
vertices[index1].Position = vertexPositions[bottomOuterStart + i + 1];
vertices[index2].Position = vertexPositions[bottomInnerStart + i + 1];
vertices[index3].Position = vertexPositions[bottomInnerStart + i];
}
else
{
// fill downwards to the step height.
vertices[index0].Position = vertexPositions[outerStart + (i * 2) + 1] - new Vector3(0.0f, stepHeight, 0.0f);
vertices[index1].Position = vertexPositions[outerStart + (i * 2) + 2] - new Vector3(0.0f, stepHeight, 0.0f);
vertices[index2].Position = vertexPositions[innerStart + (i * 2) + 2] - new Vector3(0.0f, stepHeight, 0.0f);
vertices[index3].Position = vertexPositions[innerStart + (i * 2) + 1] - new Vector3(0.0f, stepHeight, 0.0f);
}
if (slopedCeiling)
{
// create a smooth ceiling slope.
vertices[index0].Position = vertexPositions[outerStart + (i * 2) + 1] - new Vector3(0.0f, stepHeight * 2.0f, 0.0f);
vertices[index3].Position = vertexPositions[innerStart + (i * 2) + 1] - new Vector3(0.0f, stepHeight * 2.0f, 0.0f);
}

// calculate a normal using a virtual plane.
GenerateNormals(polygons[4]);

// update uv coordinates to prevent distortions using barnaby's genius utilities.
vertices[index0].UV = GeometryHelper.GetUVForPosition(polygons[4], vertexPositions[bottomOuterStart + i]);
vertices[index1].UV = GeometryHelper.GetUVForPosition(polygons[4], vertexPositions[bottomOuterStart + i + 1]);
vertices[index2].UV = GeometryHelper.GetUVForPosition(polygons[4], vertexPositions[bottomInnerStart + i + 1]);
vertices[index3].UV = GeometryHelper.GetUVForPosition(polygons[4], vertexPositions[bottomInnerStart + i]);
GenerateUvCoordinates(polygons[4]);



// retrieve the vertices of the back polygon.
vertices = polygons[0].Vertices;

// back panel.
vertices[index0].Position = vertexPositions[bottomOuterStart + i + 1];
vertices[index1].Position = vertexPositions[outerStart + (i * 2) + 2];
vertices[index2].Position = vertexPositions[innerStart + (i * 2) + 2];
vertices[index3].Position = vertexPositions[bottomInnerStart + i + 1];
if (fillToBottom)
{
// fill downwards to the bottom.
vertices[index0].Position = vertexPositions[bottomOuterStart + i + 1];
vertices[index1].Position = vertexPositions[outerStart + (i * 2) + 2];
vertices[index2].Position = vertexPositions[innerStart + (i * 2) + 2];
vertices[index3].Position = vertexPositions[bottomInnerStart + i + 1];
}
else
{
// fill downwards to the step height.
vertices[index0].Position = vertexPositions[outerStart + (i * 2) + 2] - new Vector3(0.0f, stepHeight, 0.0f);
vertices[index1].Position = vertexPositions[outerStart + (i * 2) + 2];
vertices[index2].Position = vertexPositions[innerStart + (i * 2) + 2];
vertices[index3].Position = vertexPositions[innerStart + (i * 2) + 2] - new Vector3(0.0f, stepHeight, 0.0f);
}
if (slopedFloor)
{
// create a smooth floor slope.
vertices[index1].Position = vertexPositions[outerStart + (i * 2) + 2 + 1];
vertices[index2].Position = vertexPositions[innerStart + (i * 2) + 2 + 1];
}

// calculate a normal using a virtual plane.
plane = new Plane(vertices[index1].Position, vertices[index2].Position, vertices[index3].Position);
vertices[index0].Normal = plane.normal;
vertices[index1].Normal = plane.normal;
vertices[index2].Normal = plane.normal;
vertices[index3].Normal = plane.normal;
GenerateNormals(polygons[0]);

// update uv coordinates to prevent distortions using barnaby's genius utilities.
GenerateUvCoordinates(polygons[0]);



generatedBrushes[i].Invalidate(true);
csgBounds.Encapsulate(generatedBrushes[i].GetBounds());
Expand All @@ -320,6 +459,23 @@ public override void Invalidate (bool polygonsChanged)
m_LastKnownExtents = localBounds.extents;
m_LastKnownPosition = transform.localPosition;
}

/// <summary>
/// Generates the UV coordinates for a <see cref="Polygon"/> automatically.
/// </summary>
/// <param name="polygon">The polygon to be updated.</param>
private void GenerateUvCoordinates(Polygon polygon)
{
foreach (Vertex vertex in polygon.Vertices)
vertex.UV = GeometryHelper.GetUVForPosition(polygon, vertex.Position);
}

private void GenerateNormals(Polygon polygon)
{
Plane plane = new Plane(polygon.Vertices[1].Position, polygon.Vertices[2].Position, polygon.Vertices[3].Position);
foreach (Vertex vertex in polygon.Vertices)
vertex.Normal = plane.normal;
}
}
}

Expand Down
Loading