Skip to content

Instantly share code, notes, and snippets.

@mataneil
Last active August 29, 2015 14:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mataneil/4745f7b707f0659b9fc6 to your computer and use it in GitHub Desktop.
Save mataneil/4745f7b707f0659b9fc6 to your computer and use it in GitHub Desktop.
//
// Created by Matan Eilat on 9/21/14.
// Copyright 2014 JoyTunes. All rights reserved.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the Simplified BSD License.
//
#import <Foundation/Foundation.h>
#import <Sparrow/SPDisplayObject.h>
@interface JTLine : SPDisplayObject
+ (JTLine *)lineWithLength:(float)length;
+ (JTLine *)lineWithLength:(float)length andThickness:(float)thickness;
+ (JTLine *)lineWithCoords:(float)x1 :(float)y1 :(float)x2 :(float)y2;
+ (JTLine *)lineWithCoords:(float)x1 :(float)y1 :(float)x2 :(float)y2 andThickness:(float)thickness;
@property (nonatomic, assign) float x2;
@property (nonatomic, assign) float y2;
@property (nonatomic, assign) uint color;
@property (nonatomic, assign) uint startColor;
@property (nonatomic, assign) uint endColor;
@property (nonatomic, assign) float startAlpha;
@property (nonatomic, assign) float endAlpha;
@property (nonatomic, assign) float thickness;
- (JTLine *)initWithSize:(float)length;
- (JTLine *)initWithLength:(float)length andThickness:(float)thickness;
- (JTLine *)initWithCoords:(float)x1 :(float)y1 :(float)x2 :(float)y2;
- (JTLine *)initWithCoords:(float)x1 :(float)y1 :(float)x2 :(float)y2 andThickness:(float)thickness;
@end
//
// Created by Matan Eilat on 9/21/14.
// Copyright 2014 JoyTunes. All rights reserved.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the Simplified BSD License.
//
#import <Sparrow/SPBaseEffect.h>
#import <Sparrow/SPVertexData.h>
#import <Sparrow/SPRenderSupport.h>
#import <Sparrow/SPPoint.h>
#import <Sparrow/SPBlendMode.h>
#import <GLKit/GLKit.h>
#import "JTLine.h"
@interface JTLine ()
@property (nonatomic, strong) SPBaseEffect *baseEffect;
@property (nonatomic, strong) SPVertexData *vertexData;
@property (nonatomic, assign) GLuint vertexBufferName;
@property (nonatomic, assign) BOOL syncRequired;
@end
@implementation JTLine
- (JTLine *)init {
return [self initWithCoords:0:0:50.0f:0 andThickness:1.0f];
}
- (JTLine *)initWithSize:(float)length {
return [self initWithCoords:0:0:length:0 andThickness:1.0f];
}
- (JTLine *)initWithLength:(float)length andThickness:(float)thickness {
return [self initWithCoords:0:0:length:0 andThickness:thickness];
}
- (JTLine *)initWithCoords:(float)x1 :(float)y1 :(float)x2 :(float)y2 {
return [self initWithCoords:x1:y1:x2:y2 andThickness:1.0f];
}
- (JTLine *)initWithCoords:(float)x1 :(float)y1 :(float)x2 :(float)y2 andThickness:(float)thickness {
self = [super init];
if (self) {
self.thickness = thickness;
self.baseEffect = [[SPBaseEffect alloc] init];
[self setupBufferDataWithCoords:x1 :y1 :x2 :y2];
self.syncRequired = YES;
}
return self;
}
- (void)setupBufferDataWithCoords:(float)x1 :(float)y1 :(float)x2 :(float)y2 {
self.vertexData = [[SPVertexData alloc] initWithSize:2 premultipliedAlpha:NO];
[self.vertexData setPositionWithX:x1 y:y1 atIndex:0];
[self.vertexData setPositionWithX:x2 y:y2 atIndex:1];
for (int i = 0; i < self.vertexData.numVertices; ++i) {
self.vertexData.vertices[i].color = SPVertexColorMakeWithColorAndAlpha(0xffffff, 1.0f);
}
}
+ (JTLine *)lineWithLength:(float)length {
return [[JTLine alloc] initWithSize:length];
}
+ (JTLine *)lineWithLength:(float)length andThickness:(float)thickness {
return [[JTLine alloc] initWithLength:length andThickness:thickness];
}
+ (JTLine *)lineWithCoords:(float)x1 :(float)y1 :(float)x2 :(float)y2 {
return [[JTLine alloc] initWithCoords:x1:y1:x2:y2];
}
+ (JTLine *)lineWithCoords:(float)x1 :(float)y1 :(float)x2 :(float)y2 andThickness:(float)thickness {
return [[JTLine alloc] initWithCoords:x1:y1:x2:y2 andThickness:thickness];
}
- (void)dealloc {
[self destroyBuffers];
}
- (void)render:(SPRenderSupport *)support {
if (self.syncRequired) {
[self syncBuffers];
}
[support finishQuadBatch];
self.baseEffect.mvpMatrix = support.mvpMatrix;
self.baseEffect.alpha = support.alpha;
[self.baseEffect prepareToDraw];
int attribPosition = self.baseEffect.attribPosition;
int attribColor = self.baseEffect.attribColor;
[SPBlendMode applyBlendFactorsForBlendMode:support.blendMode
premultipliedAlpha:self.vertexData.premultipliedAlpha];
glEnableVertexAttribArray(attribPosition);
glEnableVertexAttribArray(attribColor);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferName);
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)));
glLineWidth(self.thickness);
glDrawArrays(GL_LINES, 0, 2);
}
- (void)syncBuffers {
if (!self.vertexBufferName) {
[self createBuffers];
}
// Bind the buffer object array to the GL_ARRAY_BUFFER target buffer
glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferName);
// Send the line data over to the target buffer in GPU RAM
glBufferData(
GL_ARRAY_BUFFER, // the target buffer
sizeof(SPVertex) * self.vertexData.numVertices, // the number of bytes to put into the buffer
self.vertexData.vertices, // a pointer to the data being copied
GL_STATIC_DRAW); // the usage pattern of the data
self.syncRequired = NO;
}
- (void)createBuffers {
// First, we destory the existing buffers.
[self destroyBuffers];
// Have OpenGL generate a buffer name and store it in the buffer object array
glGenBuffers(1, &_vertexBufferName);
self.syncRequired = YES;
}
- (void)destroyBuffers {
if (_vertexBufferName) {
glDeleteBuffers(1, &_vertexBufferName);
_vertexBufferName = 0;
}
}
- (SPRectangle *)boundsInSpace:(SPDisplayObject *)targetSpace {
SPMatrix *matrix = targetSpace == self ? nil : [self transformationMatrixToSpace:targetSpace];
return [self.vertexData boundsAfterTransformation:matrix atIndex:0 numVertices:2];
}
- (void)setX2:(float)x2 {
SPPoint *currentPosition = [self.vertexData positionAtIndex:1];
[self.vertexData setPositionWithX:x2 y:currentPosition.y atIndex:1];
self.syncRequired = YES;
}
- (void)setY2:(float)y2 {
SPPoint *currentPosition = [self.vertexData positionAtIndex:1];
[self.vertexData setPositionWithX:currentPosition.x y:y2 atIndex:1];
self.syncRequired = YES;
}
- (void)setColor:(uint)color {
[self.vertexData setColor:color];
self.syncRequired = YES;
}
- (void)setStartColor:(uint)color {
[self.vertexData setColor:color atIndex:0];
self.syncRequired = YES;
}
- (void)setEndColor:(uint)color {
[self.vertexData setColor:color atIndex:0];
self.syncRequired = YES;
}
- (void)setStartAlpha:(float)alpha {
if (alpha < 0) alpha = 0;
if (alpha > 1.0f) alpha = 1.0f;
[self.vertexData setAlpha:alpha atIndex:0];
self.syncRequired = YES;
}
- (void)setEndAlpha:(float)alpha {
if (alpha < 0) alpha = 0;
if (alpha > 1.0f) alpha = 1.0f;
[self.vertexData setAlpha:alpha atIndex:1];
self.syncRequired = YES;
}
- (float)x2 {
return [self.vertexData positionAtIndex:1].x;
}
- (float)y2 {
return [self.vertexData positionAtIndex:1].y;
}
- (uint)color {
return self.startColor;
}
- (uint)startColor {
return [self.vertexData colorAtIndex:0];
}
- (uint)endColor {
return [self.vertexData colorAtIndex:1];
}
- (float)startAlpha {
return [self.vertexData alphaAtIndex:0];
}
- (float)endAlpha {
return [self.vertexData alphaAtIndex:1];
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment