Skip to content

Instantly share code, notes, and snippets.

@PrimaryFeather
Last active December 16, 2015 01:09
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save PrimaryFeather/5352978 to your computer and use it in GitHub Desktop.
Save PrimaryFeather/5352978 to your computer and use it in GitHub Desktop.
An example for a custom display object for the Sparrow Framework.
#import "SPDisplayObject.h"
@interface Polygon : SPDisplayObject
- (id)initWithRadius:(float)radius numEdges:(int)numEdges color:(uint)color;
- (id)initWithRadius:(float)radius numEdges:(int)numEdges;
@property (nonatomic, assign) int numEdges;
@property (nonatomic, assign) float radius;
@property (nonatomic, assign) uint color;
@end
#import "Polygon.h"
@implementation Polygon
{
float _radius;
int _numEdges;
uint _color;
BOOL _requiresUpdate;
SPBaseEffect *_baseEffect;
SPVertexData *_vertexData;
uint _vertexBufferName;
ushort *_indexData;
uint _indexBufferName;
}
@synthesize color = _color;
@synthesize radius = _radius;
@synthesize numEdges = _numEdges;
- (id)initWithRadius:(float)radius numEdges:(int)numEdges color:(uint)color
{
if ((self = [super init]))
{
_radius = radius;
_numEdges = MAX(3, numEdges);
_color = color;
_vertexData = [[SPVertexData alloc] init];
_baseEffect = [[SPBaseEffect alloc] init];
_requiresUpdate = YES;
}
return self;
}
- (id)initWithRadius:(float)radius numEdges:(int)numEdges
{
return [self initWithRadius:radius numEdges:numEdges color:SP_WHITE];
}
- (id)init
{
return [self initWithRadius:32.0f numEdges:5];
}
- (void)dealloc
{
free(_indexData);
}
- (void)update
{
[self setupVertices];
[self createBuffers];
_requiresUpdate = NO;
}
- (void)setupVertices
{
// set up vertex data
_vertexData.numVertices = _numEdges + 1;
_vertexData.color = _color;
for (int i=0; i<_numEdges; ++i)
{
SPPoint *edge = [[SPPoint alloc] initWithPolarLength:_radius angle:i*2*PI / _numEdges];
[_vertexData setPosition:edge atIndex:i];
}
[_vertexData setPositionWithX:0.0f y:0.0f atIndex:_numEdges]; // center vertex
// set up index data
int numIndices = _numEdges * 3;
if (!_indexData) _indexData = malloc(sizeof(ushort) * numIndices);
else _indexData = realloc(_indexData, sizeof(ushort) * numIndices);
for (int i=0; i<_numEdges; ++i)
{
_indexData[i*3] = _numEdges;
_indexData[i*3+1] = i;
_indexData[i*3+2] = (i+1) % _numEdges;
}
}
- (void)createBuffers
{
int numVertices = _numEdges + 1;
int numIndices = _numEdges * 3;
if (_vertexBufferName) glDeleteBuffers(1, &_vertexBufferName);
if (_indexBufferName) glDeleteBuffers(1, &_indexBufferName);
glGenBuffers(1, &_vertexBufferName);
glGenBuffers(1, &_indexBufferName);
if (!_vertexBufferName || !_indexBufferName)
[NSException raise:SP_EXC_OPERATION_FAILED format:@"could not create vertex buffers"];
glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferName);
glBufferData(GL_ARRAY_BUFFER, sizeof(SPVertex) * numVertices, _vertexData.vertices,
GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBufferName);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(ushort) * numIndices, _indexData, GL_STATIC_DRAW);
}
- (void)render:(SPRenderSupport *)support
{
if (_requiresUpdate) [self update];
[support finishQuadBatch]; // finish previously batched quads
[support addDrawCalls:1]; // update stats display
_baseEffect.mvpMatrix = support.mvpMatrix;
_baseEffect.alpha = support.alpha;
[_baseEffect prepareToDraw];
[SPBlendMode applyBlendFactorsForBlendMode:support.blendMode
premultipliedAlpha:_vertexData.premultipliedAlpha];
int attribPosition = _baseEffect.attribPosition;
int attribColor = _baseEffect.attribColor;
glEnableVertexAttribArray(attribPosition);
glEnableVertexAttribArray(attribColor);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferName);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBufferName);
glVertexAttribPointer(attribPosition, 2, GL_FLOAT, GL_FALSE, sizeof(SPVertex),
(void *)(offsetof(SPVertex, position)));
glVertexAttribPointer(attribColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(SPVertex),
(void *)(offsetof(SPVertex, color)));
int numIndices = _numEdges * 3;
glDrawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_SHORT, 0);
}
- (SPRectangle*)boundsInSpace:(SPDisplayObject*)targetSpace
{
SPMatrix *matrix = [self transformationMatrixToSpace:targetSpace];
return [_vertexData boundsAfterTransformation:matrix];
}
- (void)setNumEdges:(int)numEdges
{
if (numEdges != _numEdges)
{
_numEdges = numEdges;
_requiresUpdate = YES;
}
}
- (void)setRadius:(float)radius
{
if (radius != _radius)
{
_radius = radius;
_requiresUpdate = YES;
}
}
- (void)setColor:(uint)color
{
if (color != _color)
{
_color = color;
_requiresUpdate = YES;
}
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment