Last active
May 19, 2019 18:08
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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