Tuesday, 16 February 2010

Stock Market Hero submitted

Just managed to submit make my first submission to the app store. Getting a distribution profile was a pain.. I'll post more details after I've got some sleep..


Tuesday, 9 February 2010

Graph Normalization

Just implemented a new feature called Graph Normalization as suggested by Jeff from Forex Fundamental Analysis. The problem previously was when you chart stocks with extreme differences in price levels, it's impossible to visualize the graph shapes together.



But now with the Graph Normalization feature, you can normalize the graphs to see the pattern by clicking on the graph you wish to normalize the rest by..


Then selecting Normalize Graph..


Now all the graphs will be normalized to the chosen scale..


You can denormalize the charts using the same option.

If anyone has any requests/suggestions, feel free to drop me a line.

Font pages

I recently switched from rendering texture strings to font pages. The difference between the two is for texture strings you'd render the string into a bitmap and assign the image to an openGL handle. For a font page, you'd create all the characters of the font required and then when rendering a string, you'd fetch the characters required individually from the created page to render one by one.

The reason for switching was to display a more dynamic text such as an OSD counter. With the old system I'd have to have to constantly create and release different images representing the numbers required, which would be impractical.





So here's how rendering text using a font page works.

First we initialize our class, where we create a bitmap with all the characters from the font required, and paste them one by one onto the page, incrementing the width and height as we paste along..
 -(id)init  
{  
if( self = [super init] )  
{  
// Initialise our texture page  
UIFont *font = [UIFont fontWithName:@"Trebuchet MS" size:32];  
width = 512;  
height = 256;  
widthAspect = ( width * gView->actualScreenSizeMultiple.width );  
heightAspect = ( height * gView->actualScreenSizeMultiple.height );  
const CGSize textureSizeMultiple = CGSizeMake( 1.0f / width, 1.0f / height );

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();  
void *data = calloc( height, width );  
CGContextRef context = CGBitmapContextCreate( data, width, height, 8, width, colorSpace, kCGImageAlphaNone );  
CGColorSpaceRelease( colorSpace );  
CGContextSetGrayFillColor( context, 1.0f, 1.0f );  
UIGraphicsPushContext( context );  

// Create our characters  
float x = 0.0f, y = 0.0f;  
float maxY = 0.0f;  
for( uint i=0; i<128; ++i )  
{  
NSString *string = [[NSString alloc] initWithString:@"£"];  
letters[i].stringSize = [string sizeWithFont:font];  
float endX = x + letters[i].stringSize.width + 1.0f;  
if( endX > 512.0f )  
{  
x = 0.0f;  
y += maxY + 1.0f;  
maxY = letters[i].stringSize.height;  
endX = letters[i].stringSize.width + 1.0f;  
}  

// Check if we've reached the end of the page
if( letters[i].stringSize.height > maxY )  
{  
maxY = letters[i].stringSize.height;  
}  

letters[i].start.x = x;  
letters[i].start.y = y;  
[string drawInRect:CGRectMake( x, y, letters[i].stringSize.width, letters[i].stringSize.height) withFont:font lineBreakMode:UILineBreakModeWordWrap alignment:UITextAlignmentLeft ];  
x = endX;  
// Normalize  
letters[i].stringSize.width *= textureSizeMultiple.width;  
letters[i].stringSize.height *= textureSizeMultiple.height;  
letters[i].start.x *= textureSizeMultiple.width;  
letters[i].start.y = 1.0f - ( letters[i].start.y * textureSizeMultiple.height );  
letters[i].end.x = letters[i].start.x + letters[i].stringSize.width;  
letters[i].end.y = letters[i].start.y - letters[i].stringSize.height;  
[string release];  
}  
assert( maxY + y < height ); 

// Finish our texture page  
UIGraphicsPopContext();  
glGenTextures( 1, &name );  
BindTexture( name );  
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );  
glTexImage2D( GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, data );  
CGContextRelease( context );  
free( data );  
BindTexture( 0 );  
}  
return self;  
}  


Now to render any given string, we just look up the letters one by one and render each one with their stored sizes..
 -(void)renderText:(const char*)string length:(const uint)length x:(const float)x y:(const float)y centered:(const BOOL)centered size:(const float)size  
{    
BindTexture( name );  

// Find out our width so we can center the text  
float totalWidth = 0.0f, maxHeight = 0.0f;  
float widths[length], heights[length];  
for( uint i=0; i<length; ++i )  
{  
const Letters *letter = [self getLetter:string[i]];  
if( letter != nil )  
{  
widths[i] = widthAspect * letter->stringSize.width * size;  
totalWidth += widths[i];  
heights[i] = heightAspect * letter->stringSize.height * size;  
maxHeight = MAX( maxHeight, heights[i] );  
}  
}  

CGPoint start = CGPointMake( x, y );  
if( centered )  
{  
start.x -= totalWidth * 0.5f;  
start.y -= maxHeight * 0.5f;  
}  

CGPoint currentStart = start;  
for( uint i=0; i<length; ++i )  
{  
const Letters *letter = [self getLetter:string[i]];  
if( letter != nil )  
{  
// Calculate end point  
CGPoint orientatedStart = currentStart;  
CGPoint end;  
end.x = orientatedStart.x + widths[i];  
end.y = orientatedStart.y + heights[i];  

const GLfloat texCoords[] =   
{  
letter->start.x, letter->start.y,  
letter->end.x, letter->start.y,  
letter->start.x, letter->end.y,  
letter->end.x, letter->end.y  
};  
glTexCoordPointer( 2, GL_FLOAT, 0, texCoords );  
RenderSquare( orientatedStart, end );  
currentStart.x += widths[i];  
}  
}  

BindTexture( 0 );  
DefaultTexCoords();  
}  

Any issues, let me know.

Friday, 5 February 2010

3D Level Generation

So, I've been experimenting with generating levels based off actual stock market history data.

Here's a little preview of the result..

iGrapher 3D Level Generation

So I've been working on a 3D engine for the iPhone and decided to quickly throw together a level generated from non-other than stock market history.

Check it out..