No matter what I do I can't get it to work. It just won't render correctly. Here's the complete code:
QiblaArcLayer.h
#import <UIKit/UIKit.h>
@interface QiblaArcLayer : CCColorLayer {
BOOL DrawingMoonArc;
BOOL DrawingSunArc;
BOOL DrawingQiblaArc;
float QiblaAngle;
float MoonAngle;
float SunAngle;
float DegreeToDrawQibla;
float DegreeToDrawSun;
float DegreeToDrawMoon;
float factor;
// Qibla
float *qiblaverticesNeg;
// Sun
float *sunverticesNeg;
// Moon
float *moonverticesNeg;
BOOL CanSmoothLines;
BOOL IsRendering;
}
@property (nonatomic, assign) BOOL DrawingMoonArc;
@property (nonatomic, assign) BOOL DrawingSunArc;
@property (nonatomic, assign) BOOL DrawingQiblaArc;
@property (nonatomic, assign) BOOL CanSmoothLines;
@property (nonatomic, assign) BOOL IsRendering;
@property (nonatomic, assign) float QiblaAngle;
@property (nonatomic, assign) float MoonAngle;
@property (nonatomic, assign) float SunAngle;
@end
QiblaArcLayer.m
#import "QiblaArcLayer.h"
@implementation QiblaArcLayer
@synthesize DrawingQiblaArc;
@synthesize DrawingSunArc;
@synthesize DrawingMoonArc;
@synthesize QiblaAngle;
@synthesize MoonAngle;
@synthesize SunAngle;
@synthesize CanSmoothLines;
@synthesize IsRendering;
void drawCubicBezier(CGPoint origin, CGPoint control1, CGPoint control2, CGPoint destination, int segments)
{
CGPoint vertices[segments + 1];
float t = 0.0;
for(int i = 0; i < segments; i++)
{
float x = pow(1 - t, 3) * origin.x + 3.0 * pow(1 - t, 2) * t * control1.x + 3.0 * (1 - t) * t * t * control2.x + t * t * t * destination.x;
float y = pow(1 - t, 3) * origin.y + 3.0 * pow(1 - t, 2) * t * control1.y + 3.0 * (1 - t) * t * t * control2.y + t * t * t * destination.y;
vertices[i] = CGPointMake(x, y);
t += 1.0 / segments;
}
vertices[segments] = destination;
glVertexPointer(2, GL_FLOAT, 0, vertices);
glDrawArrays(GL_LINE_STRIP, 0, segments+1);
}
void ccDrawArc( CGPoint center, float r, float degrees, float *vertices)
{
if (vertices == nil) {
return;
}
// Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
// Needed states: GL_VERTEX_ARRAY,
// Unneeded states: GL_TEXTURE_2D, GL_TEXTURE_COORD_ARRAY, GL_COLOR_ARRAY
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
// 2 lines define a single degree for smoothness
int segments = ((int)round(degrees));
glVertexPointer(2, GL_FLOAT, 0, vertices);
glDrawArrays(GL_POINTS, 0, segments);
// restore default state
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnable(GL_TEXTURE_2D);
}
// on "init" you need to initialize your instance
-(id) init
{
// always call "super" init
// Apple recommends to re-assign "self" with the "super" return value
if( (self=[super initWithColor:ccc4(255,255,255,0)] )) {
// Enable touch events
self.isTouchEnabled = NO;
factor = [[CCDirector sharedDirector] contentScaleFactor];
// qiblavertices = (float*)malloc(2*360*sizeof(float));
qiblaverticesNeg = nil;
sunverticesNeg = nil;
moonverticesNeg = nil;
qiblaverticesNeg = (float*)malloc(2*360*sizeof(float));
sunverticesNeg = (float*)malloc(2*360*sizeof(float));
moonverticesNeg = (float*)malloc(2*360*sizeof(float));
CGPoint center = ccp((294.0*factor)/2, (294.0*factor)/2);
for (int i=0, angle=1;i<360*2;i+=2,angle+=1) {
float r = 87*factor;
qiblaverticesNeg[i] = r * cos(CC_DEGREES_TO_RADIANS((angle-90)*-1)) + center.x;
qiblaverticesNeg[i+1] = r * sin(CC_DEGREES_TO_RADIANS((angle-90)*-1)) + center.y;
r = 113*factor;
sunverticesNeg[i] = r * cos(CC_DEGREES_TO_RADIANS((angle-90)*-1)) + center.x;
sunverticesNeg[i+1] = r * sin(CC_DEGREES_TO_RADIANS((angle-90)*-1)) + center.y;
r = 65*factor;
moonverticesNeg[i] = r * cos(CC_DEGREES_TO_RADIANS((angle-90)*-1)) + center.x;
moonverticesNeg[i+1] = r * sin(CC_DEGREES_TO_RADIANS((angle-90)*-1)) + center.y;
}
CanSmoothLines = NO;
}
return self;
}
- (void) setDrawingQiblaArc:(BOOL) newval {
if (DrawingQiblaArc != newval) {
DrawingQiblaArc = newval;
DegreeToDrawQibla = 0;
}
}
- (void) setDrawingSunArc:(BOOL) newval {
if (DrawingSunArc != newval) {
DrawingSunArc = newval;
DegreeToDrawSun = 0;
}
}
- (void) setDrawingMoonArc:(BOOL) newval {
if (DrawingMoonArc != newval) {
DrawingMoonArc = newval;
DegreeToDrawMoon = 0;
}
}
- (void) draw {
CanSmoothLines = YES;
// QLog(@" Draw Qibla: %i, Sun: %i, Angle: %f", DrawingQiblaArc, DrawingSunArc, SunAngle);
if (DrawingQiblaArc || DrawingSunArc || DrawingMoonArc) {
if (CanSmoothLines) {
glEnable(GL_POINT_SMOOTH);
glHint(GL_POINT_SMOOTH_HINT, GL_FASTEST);
}
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// line: color, width, anti-aliased
BOOL restoreVals = NO;
if (DrawingQiblaArc && DegreeToDrawQibla <= QiblaAngle && QiblaAngle != 0){
restoreVals = YES;
glColor4ub(0,0,0,12);
float Radius = 87*factor;
float BarWidth = 18*factor;
glPointSize(BarWidth);
ccDrawArc(ccp((294.0*factor)/2, (294.0*factor)/2), Radius, QiblaAngle, qiblaverticesNeg);
}
if (DrawingSunArc && DegreeToDrawSun <= SunAngle && SunAngle != 0){
restoreVals = YES;
glColor4ub(216,152,27,200);
float Radius = 113*factor;
float BarWidth = 6*factor;
glPointSize(BarWidth);
ccDrawArc(ccp((294.0*factor)/2, (294.0*factor)/2), Radius, SunAngle, sunverticesNeg);
}
if (DrawingMoonArc && DegreeToDrawMoon <= MoonAngle && MoonAngle != 0){
restoreVals = YES;
glColor4ub(160,160,160,80);
float Radius = 65*factor;
float BarWidth = 6*factor;
glPointSize(BarWidth);
ccDrawArc(ccp((294.0*factor)/2, (294.0*factor)/2), Radius, MoonAngle, moonverticesNeg);
}
// restore original values
if (restoreVals) {
glColor4ub(255,255,255,255);
glPointSize(1);
if (CanSmoothLines) {
glDisable(GL_POINT_SMOOTH);
}
}
}
}
- (void) dealloc
{
if (!qiblaverticesNeg)
free(qiblaverticesNeg);
if (!sunverticesNeg)
free(sunverticesNeg);
if (!moonverticesNeg)
free(moonverticesNeg);
[super dealloc];
}
@end
Calling Code:
QiblaArcLayer *qiblaDial = [QiblaArcLayer node];
[qiblaDial setContentSize: CGSizeMake(294*[[CCDirector sharedDirector] contentScaleFactor], 294*[[CCDirector sharedDirector] contentScaleFactor])];
[qiblaDial setPosition: ccp(0, 0)];
[compassDial addChild:qiblaDial z:0 tag: kTagArcLayer];
CCRenderTexture *renderedArcLayer = [CCRenderTexture renderTextureWithWidth:294*[[CCDirector sharedDirector] contentScaleFactor] height:294*[[CCDirector sharedDirector] contentScaleFactor]];
[renderedArcLayer setVisible: NO];
[renderedArcLayer setPosition: ccp((294*[[CCDirector sharedDirector] contentScaleFactor])/2, (294*[[CCDirector sharedDirector] contentScaleFactor])/2)];
[[renderedArcLayer sprite] setBlendFunc:(ccBlendFunc) {GL_ONE,GL_ONE_MINUS_SRC_ALPHA}];
[compassDial addChild: renderedArcLayer z:0 tag: kTagArcRenderedLayer];
// Set some angle:
qiblaDial.QiblaAngle = 218;
qiblaDial.SunAngle = 65;
// Now swap views
CCRenderTexture *renderedArcLayer = (CCRenderTexture*) [compasssprite getChildByTag: kTagArcRenderedLayer];
renderedArcLayer.visible = YES;
qiblaDial.IsRendering = YES;
[renderedArcLayer begin];
[qiblaDial visit];
[renderedArcLayer end];
qiblaDial.IsRendering = NO;
qiblaDial.visible = NO;