Last active
December 17, 2015 22:09
-
-
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.
This file contains hidden or 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
#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 |
This file contains hidden or 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
#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