Skip to content

Instantly share code, notes, and snippets.

@PrimaryFeather
Last active December 17, 2015 22: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/5679832 to your computer and use it in GitHub Desktop.
Save PrimaryFeather/5679832 to your computer and use it in GitHub Desktop.
An example for a custom display object for the Sparrow Framework - this time with a texture.
#import "SPDisplayObject.h"
@interface TexturedPolygon : SPDisplayObject
- (id)initWithRadius:(float)radius numEdges:(int)numEdges texture:(SPTexture *)texture;
@property (nonatomic, assign) int numEdges;
@property (nonatomic, assign) float radius;
@property (nonatomic, strong) SPTexture *texture;
@property (nonatomic, assign) uint color;
@end
#import "TexturedPolygon.h"
@implementation TexturedPolygon
{
float _radius;
int _numEdges;
SPTexture *_texture;
uint _color;
BOOL _requiresUpdate;
SPBaseEffect *_baseEffect;
SPVertexData *_vertexData;
uint _vertexBufferName;
ushort *_indexData;
uint _indexBufferName;
}
@synthesize color = _color;
@synthesize texture = _texture;
@synthesize radius = _radius;
@synthesize numEdges = _numEdges;
- (id)initWithRadius:(float)radius numEdges:(int)numEdges texture:(SPTexture *)texture
{
if ((self = [super init]))
{
_radius = radius;
_numEdges = MAX(3, numEdges);
_texture = texture;
_color = SP_WHITE;
_vertexData = [[SPVertexData alloc] init];
_baseEffect = [[SPBaseEffect alloc] init];
_requiresUpdate = YES;
}
return self;
}
- (id)init
{
return nil;
}
- (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)
{
// set vertex position
SPPoint *edge = [[SPPoint alloc] initWithPolarLength:_radius angle:i*2*PI / _numEdges];
[_vertexData setPosition:edge atIndex:i];
// set texture coordinates
[_vertexData setTexCoordsWithX:0.5f + edge.x / (2 * _radius)
y:0.5f + edge.y / (2 * _radius)
atIndex:i];
}
// add center vertex
[_vertexData setPositionWithX:0.0f y:0.0f atIndex:_numEdges];
[_vertexData setTexCoordsWithX:0.5f y:0.5f atIndex:_numEdges];
// above, we have inserted the "high level" vertex data, using a [0-1] range. The actual
// texture coordinates for OpenGL might differ; the following method will adjust them.
[_texture adjustVertexData:_vertexData atIndex:0 numVertices:_numEdges+1];
// ### 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.texture = _texture;
[_baseEffect prepareToDraw];
[SPBlendMode applyBlendFactorsForBlendMode:support.blendMode
premultipliedAlpha:_vertexData.premultipliedAlpha];
int attribPosition = _baseEffect.attribPosition;
int attribColor = _baseEffect.attribColor;
int attribTexCoords = _baseEffect.attribTexCoords;
glEnableVertexAttribArray(attribPosition);
glEnableVertexAttribArray(attribColor);
glEnableVertexAttribArray(attribTexCoords);
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)));
glVertexAttribPointer(attribTexCoords, 2, GL_FLOAT, GL_FALSE, sizeof(SPVertex),
(void *)(offsetof(SPVertex, texCoords)));
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)setTexture:(SPTexture *)texture
{
if (texture != _texture)
{
_texture = texture;
_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