Skip to content

Instantly share code, notes, and snippets.

@PrimaryFeather
Last active July 31, 2017 14:53
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 7 You must be signed in to fork a gist
  • Save PrimaryFeather/2352107 to your computer and use it in GitHub Desktop.
Save PrimaryFeather/2352107 to your computer and use it in GitHub Desktop.
A custom display object for Starling, rendering a regular n-sided polygon.
package utils
{
import com.adobe.utils.AGALMiniAssembler;
import flash.display3D.*;
import flash.geom.*;
import starling.core.RenderSupport;
import starling.core.Starling;
import starling.display.DisplayObject;
import starling.errors.MissingContextError;
import starling.events.Event;
import starling.utils.VertexData;
/** This custom display objects renders a regular, n-sided polygon. */
public class Polygon extends DisplayObject
{
private static var PROGRAM_NAME:String = "polygon";
// custom members
private var mRadius:Number;
private var mNumEdges:int;
private var mColor:uint;
// vertex data
private var mVertexData:VertexData;
private var mVertexBuffer:VertexBuffer3D;
// index data
private var mIndexData:Vector.<uint>;
private var mIndexBuffer:IndexBuffer3D;
// helper objects (to avoid temporary objects)
private static var sHelperMatrix:Matrix = new Matrix();
private static var sRenderAlpha:Vector.<Number> = new <Number>[1.0, 1.0, 1.0, 1.0];
/** Creates a regular polygon with the specified redius, number of edges, and color. */
public function Polygon(radius:Number, numEdges:int=6, color:uint=0xffffff)
{
if (numEdges < 3) throw new ArgumentError("Invalid number of edges");
mRadius = radius;
mNumEdges = numEdges;
mColor = color;
// setup vertex data and prepare shaders
setupVertices();
createBuffers();
registerPrograms();
// handle lost context
Starling.current.addEventListener(Event.CONTEXT3D_CREATE, onContextCreated);
}
/** Disposes all resources of the display object. */
public override function dispose():void
{
Starling.current.removeEventListener(Event.CONTEXT3D_CREATE, onContextCreated);
if (mVertexBuffer) mVertexBuffer.dispose();
if (mIndexBuffer) mIndexBuffer.dispose();
super.dispose();
}
private function onContextCreated(event:Event):void
{
// the old context was lost, so we create new buffers and shaders.
createBuffers();
registerPrograms();
}
/** Returns a rectangle that completely encloses the object as it appears in another
* coordinate system. */
public override function getBounds(targetSpace:DisplayObject, resultRect:Rectangle=null):Rectangle
{
if (resultRect == null) resultRect = new Rectangle();
var transformationMatrix:Matrix = targetSpace == this ?
null : getTransformationMatrix(targetSpace, sHelperMatrix);
return mVertexData.getBounds(transformationMatrix, 0, -1, resultRect);
}
/** Creates the required vertex- and index data and uploads it to the GPU. */
private function setupVertices():void
{
var i:int;
// create vertices
mVertexData = new VertexData(mNumEdges+1);
mVertexData.setUniformColor(mColor);
for (i=0; i<mNumEdges; ++i)
{
var edge:Point = Point.polar(mRadius, i*2*Math.PI / mNumEdges);
mVertexData.setPosition(i, edge.x, edge.y);
}
mVertexData.setPosition(mNumEdges, 0.0, 0.0); // center vertex
// create indices that span up the triangles
mIndexData = new <uint>[];
for (i=0; i<mNumEdges; ++i)
mIndexData.push(mNumEdges, i, (i+1)%mNumEdges);
}
/** Creates new vertex- and index-buffers and uploads our vertex- and index-data to those
* buffers. */
private function createBuffers():void
{
var context:Context3D = Starling.context;
if (context == null) throw new MissingContextError();
if (mVertexBuffer) mVertexBuffer.dispose();
if (mIndexBuffer) mIndexBuffer.dispose();
mVertexBuffer = context.createVertexBuffer(mVertexData.numVertices, VertexData.ELEMENTS_PER_VERTEX);
mVertexBuffer.uploadFromVector(mVertexData.rawData, 0, mVertexData.numVertices);
mIndexBuffer = context.createIndexBuffer(mIndexData.length);
mIndexBuffer.uploadFromVector(mIndexData, 0, mIndexData.length);
}
/** Renders the object with the help of a 'support' object and with the accumulated alpha
* of its parent object. */
public override function render(support:RenderSupport, alpha:Number):void
{
// always call this method when you write custom rendering code!
// it causes all previously batched quads/images to render.
support.finishQuadBatch();
// make this call to keep the statistics display in sync.
support.raiseDrawCount();
sRenderAlpha[0] = sRenderAlpha[1] = sRenderAlpha[2] = 1.0;
sRenderAlpha[3] = alpha * this.alpha;
var context:Context3D = Starling.context;
if (context == null) throw new MissingContextError();
// apply the current blendmode
support.applyBlendMode(false);
// activate program (shader) and set the required buffers / constants
context.setProgram(Starling.current.getProgram(PROGRAM_NAME));
context.setVertexBufferAt(0, mVertexBuffer, VertexData.POSITION_OFFSET, Context3DVertexBufferFormat.FLOAT_2);
context.setVertexBufferAt(1, mVertexBuffer, VertexData.COLOR_OFFSET, Context3DVertexBufferFormat.FLOAT_4);
context.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, support.mvpMatrix3D, true);
context.setProgramConstantsFromVector(Context3DProgramType.VERTEX, 4, sRenderAlpha, 1);
// finally: draw the object!
context.drawTriangles(mIndexBuffer, 0, mNumEdges);
// reset buffers
context.setVertexBufferAt(0, null);
context.setVertexBufferAt(1, null);
}
/** Creates vertex and fragment programs from assembly. */
private static function registerPrograms():void
{
var target:Starling = Starling.current;
if (target.hasProgram(PROGRAM_NAME)) return; // already registered
// va0 -> position
// va1 -> color
// vc0 -> mvpMatrix (4 vectors, vc0 - vc3)
// vc4 -> alpha
var vertexProgramCode:String =
"m44 op, va0, vc0 \n" + // 4x4 matrix transform to output space
"mul v0, va1, vc4 \n"; // multiply color with alpha and pass it to fragment shader
var fragmentProgramCode:String =
"mov oc, v0"; // just forward incoming color
target.registerProgramFromSource(PROGRAM_NAME, vertexProgramCode, fragmentProgramCode);
}
/** The radius of the polygon in points. */
public function get radius():Number { return mRadius; }
public function set radius(value:Number):void { mRadius = value; setupVertices(); }
/** The number of edges of the regular polygon. */
public function get numEdges():int { return mNumEdges; }
public function set numEdges(value:int):void { mNumEdges = value; setupVertices(); }
/** The color of the regular polygon. */
public function get color():uint { return mColor; }
public function set color(value:uint):void { mColor = value; setupVertices(); }
}
}
@berndsalewski
Copy link

what happened to support.raiseDrawCount() in this version?

@PrimaryFeather
Copy link
Author

Good question! Somehow, that got lost. ;-)
I've just added it again.

@vkartaviy
Copy link

Doesn't work for me. I am using latest Starling from master and AIR 3.8.
Got: [Fault] exception, information=RangeError: Error #3610: Stream 1 vertex offset is out of bounds. on calling context.drawTriangles(mIndexBuffer, 0, mNumEdges);

@leefj
Copy link

leefj commented Nov 11, 2016

it with comple errors in starling 2.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment