Skip to content

Instantly share code, notes, and snippets.

@JohnBlackburne
Last active May 19, 2019 18:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JohnBlackburne/f99e4494449c9f487abc9805f5079807 to your computer and use it in GitHub Desktop.
Save JohnBlackburne/f99e4494449c9f487abc9805f5079807 to your computer and use it in GitHub Desktop.
A Starling (https://github.com/Gamua/Starling-Framework) extension to generate Meshes with antialiased edges
package starling.extensions
{
import flash.geom.Point;
import starling.display.Mesh;
import starling.geom.Polygon;
import starling.rendering.IndexData;
import starling.rendering.VertexData;
public class AAMesh extends Mesh
{
private static var _tempPoly :Polygon = new Polygon();
private static var _p0 :Point = new Point();
private static var _p1 :Point = new Point();
private static var _p2 :Point = new Point();
private var _sides :int;
private var _edge :Number;
private var _tint :uint;
private var _alpha :Number;
function AAMesh(poly:Polygon, edge:Number, tint:uint = 0xffffff, alpha:Number = 1)
{
var vData:VertexData, iData:IndexData;
_sides = poly.numVertices;
_edge = edge;
vData = new VertexData(BaseMesh.VERTEX_FORMAT, _sides * 2);
iData = new IndexData(_sides * 3 - 2);
super(vData, iData);
generateVertices(poly, vData);
poly.triangulate(iData);
generateEdgeTriangles(iData);
_alpha = alpha;
_tint = tint;
setVertexColours();
setRequiresRedraw();
}
public function updateShape(poly:Polygon, edge:Number = -1,
bRetriangulate:Boolean = false):void
{
if (edge > 0) _edge = edge;
if (poly.numVertices != _sides)
{
throw new Error("AAMesh:updateShape, count mismatch: "
+ String(poly.numVertices) + " != " + String(_sides));
}
if (bRetriangulate)
{
indexData.clear();
poly.triangulate(indexData);
generateVertices(poly, vertexData);
generateEdgeTriangles(indexData);
} else {
generateVertices(poly, vertexData);
}
setRequiresRedraw();
}
private function generateVertices(poly:Polygon, vData:VertexData):void
{
extendPolygon(poly, _edge / 2, _tempPoly);
_tempPoly.copyToVertexData(vData, 0);
}
private function generateEdgeTriangles(iData:IndexData):void
{
var iV0:int, iV1:int;
for (iV0 = 0; iV0 < _sides; iV0++)
{
iV1 = (iV0 + 1) % _sides;
iData.addTriangle(iV0, iV1, iV0 + _sides);
iData.addTriangle(iV1, iV1 + _sides, iV0 + _sides);
}
}
private function setVertexColours():void
{
var vData:VertexData = vertexData;
vData.colorize("color", _tint, _alpha, 0, _sides);
vData.colorize("color", _tint, 0, _sides, _sides);
}
public function set iTint(val:uint):void
{
if (val != _tint)
{
_tint = val;
setVertexColours();
setRequiresRedraw();
}
}
public function set fAlpha(val:Number):void
{
if (val != _alpha)
{
_alpha = val;
setVertexColours();
setRequiresRedraw();
}
}
public function extendPolygon(base:Polygon, edge:Number, out:Polygon):void
{
var iVerts:int, iV0:int, iV1:int, iV2:int,
fX0:Number, fY0:Number, fX1:Number, fY1:Number, fLen:Number, fTmp:Number;
iVerts = base.numVertices;
out.numVertices = 2 * iVerts;
for (iV1 = 0; iV1 < iVerts; iV1++)
{
iV0 = iV1 - 1; if (iV0 < 0) iV0 += iVerts;
iV2 = iV1 + 1; if (iV2 == iVerts) iV2 = 0;
base.getVertex(iV0, _p0);
base.getVertex(iV1, _p1);
base.getVertex(iV2, _p2);
// get edges
fX0 = _p1.x - _p0.x;
fY0 = _p1.y - _p0.y;
fX1 = _p2.x - _p1.x;
fY1 = _p2.y - _p1.y;
// normalise and perp each
fLen = 1 / Math.sqrt(fX0 * fX0 + fY0 * fY0);
fTmp = -fX0;
fX0 = fY0 * fLen;
fY0 = fTmp * fLen;
fLen = 1 / Math.sqrt(fX1 * fX1 + fY1 * fY1);
fTmp = -fX1;
fX1 = fY1 * fLen;
fY1 = fTmp * fLen;
// Dot product = p = cos θ
fLen = fX0 * fX1 + fY0 * fY1;
// θ = 2φ, (φ = half angle, bisecting vectors)
// p = cos θ = 2 cos²φ - 1 = 2q² - 1
// q = cos φ = √((1 + p) / 2)
fLen = Math.sqrt((1 + fLen) / 2);
// add to get line bisecting vectors
fX0 += fX1;
fY0 += fY1;
// normalise, scale by 1 / q and edge at the same time
fLen = edge / (fLen * Math.sqrt(fX0 * fX0 + fY0 * fY0));
// inner vertex
fX1 = _p1.x - fX0 * fLen;
fY1 = _p1.y - fY0 * fLen;
if (iV1 == 0)
{
// check first point is in poly
// if not negate fLen to flip points and recalc first one
if (!base.contains(fX1, fY1))
{
fLen = -fLen;
fX1 = _p1.x - fX0 * fLen;
fY1 = _p1.y - fY0 * fLen;
}
}
out.setVertex(iV1, fX1, fY1);
// outer vertex
fX1 = _p1.x + fX0 * fLen;
fY1 = _p1.y + fY0 * fLen;
out.setVertex(iV1 + iVerts, fX1, fY1);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment