Copy NSMutableArray into array of floats for GLES rendering - objective-c

I have an NSMutableArray called mVerticies stored as a member of my class and I'd like to place them into a float array to draw them with glVertexAttribPointer.
Normally when drawing, I would have something like:
float verticies[] = {-1, -1, 1, -1};
// ... prepare to draw
glVertexAttribPointer(GLKVertexAttribPosition,
2, GL_FLOAT, GL_FALSE, 0, verticies);
// ... draw
But in order to use the glVertexAttribPointer function, i need a float[]. The verticies are stored as an NSMutableArray because they change quite often. Is there an easy way to either store a dynamic float[] as a member or to quickly convert an NSMutableArray to a float[]?

Assuming the values are stored as NSNumbers, you can do something like this:
float *floatsArray = malloc([numbersArray count] * sizeof(float));
if (floatsArray == NULL) {
// handle error
}
[numbersArray enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(NSNumber *number, NSUInteger idx, BOOL *stop) {
floatsArray[idx] = [number floatValue];
}];
// use floatsArray
free(floatsArray);

You need to use malloc if you just want a raw chunk memory to read and write values directly.
If you have an NSArray array containing NSNumber instances:
float *vertices = malloc(sizeof(float) * [array count]);
for (int i = 0; i < [array count]; i++) {
vertices[i] = [[array objectAtIndex:i] floatValue];
}
// draw cool 3D objects and stuff
glVertexAttribPointer(....)
// then, when you're totally done with the memory
free(vertices);
Unlike Objective-C objects, the vertices pointer doesn't have a retain count, so you need to free it yourself, and keep track of when you can free it, because when you call free it will be gone immediately.

Just loop through the values. Assuming your floats are stored as NSNumbers:
NSUInteger count = [mutableVerticesArray count];
float vertices[count];
for (NSUInteger i = 0; i < count; i++) {
vertices[i] = [[mutableVerticesArray objectAtIndex:i] floatValue];
}
// Drawing etc.

Related

Most efficient way to draw lines from array of points in cocos2d

Given an NSMutableArray of dynamic CGPoints, what is the fastest and most efficient way to draw lines from array[0] to array[1], array[1] to array[2], etc.? Should I rewrite my function in C or C++ for better performance? Currently my framerate suffers dramatically when there are more than ~20 points in the array. I am using cocos2d v2.0.0-rc2 and I currently have:
-(void)draw
{
for (int i = 0; i < [points count]; i+=2)
{
CGPoint startFromArray = [[points objectAtIndex:i] CGPointValue];
CGPoint endFromArray = [[points objectAtIndex:i+1] CGPointValue];
ccDrawLine(startFromArray, endFromArray);
}
[super draw];
}
There's no need to use iteration here. Cocos2d has a built-in function called ccDrawPoly(). You can use it like this:
CGPoint *verts = malloc(sizeof(CGPoint) * [points count]);
for (int i = 0; i < [points count]; i++) {
verts[i] = [[points objectAtIndex:i] CGPointValue];
}
ccDrawPoly(verts, [points count], NO);
free(verts);
Obviously, you'll get even better performance if you store your CGPoints in a C array instead of boxing and unboxing them from NSValues, but if you really need the mutability, that can't be helped.
As for the third argument of ccDrawPoly(), setting it to YES will connect the start and end points of the array, making a closed polygon, while using NO will just make a bunch of open lines.

Sort Array of CGPoints

I am trying to figure out what the fastest/cleanest way to sort an array of CGPoints would be. I think I could achieve this using loops but that might not be the fastest and I hope it isn't the cleanest way. I would like to take an array of random CGPoints and sort them say by smallest x coordinate to largest, or smallest x and y coordinate to largest.
After the correct comment by Chuck, I've updated the answer using the sortUsingComparator method:
Here is the complete code with sample data:
First we generate 100 random values that we enter to the Array:
NSMutableArray *testArray = [[NSMutableArray alloc] initWithCapacity:100];
for (int i=0; i<100; i++) {
CGPoint testPoint = CGPointMake(arc4random()%100, arc4random()%100);
[testArray addObject:[NSValue valueWithCGPoint:testPoint]];
}
and here is the actual code to sort the array:
[testArray sortUsingComparator:^(id firstObject, id secondObject) {
CGPoint firstPoint = [firstObject CGPointValue];
CGPoint secondPoint = [secondObject CGPointValue];
return firstPoint.x>secondPoint.x;
}];
finally we can verify that the array was sorted, by printing it:
NSLog(#"%#",testArray);
The C qsort() function is probably your best bet if you just have a plain array of CGPoints. Something like this:
int compareXCoords(CGPoint *a, CGPoint *b) {
return b->x - a->x;
}
// Later:
CGPoint points[100];
// initialize points somehow
qsort(points, 100, sizeof(CGPoint), compareXCoords);
// points is now sorted by the points' x coordinates
According to my comment, it's a good solution insert them on a NSMutableArray keeping the sort you decide.
You have to do something like this:
NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:1];
CGPoint candidate;
// Look for the position it has to be
int 0;
for (CGPoint point in array) {
i++;
// Compare candidate with current point
// You have to define this condition, when point is greater than candidate
if (point > candidate) {
break;
}
}
[array insertObjectAtIndex:i-1];
Maybe my code has some errors, I can't check if it's correct now.

How to cycle through an array of CGPoints

I have created an array of 16 CGpoints representing 16 positions on a game board. This is how i set up the array CGPoint cgpointarray[16]; I would like to create a for loop to cycle through each item in the array and check if the touch is within x distance of a position (i have the position as a CGPoint. I don't have much experiance with xcode or objective c. I know the python equivalent would be
for (i in cgpointarray){
//Stuff to do
}
How would i accomplish this? Thanks
for (int i = 0; i < 16; i++){
CGPoint p = cgpointarray[i];
//do something
}
Or if you want to use the NSArray Class:
NSMutableArray *points = [NSMutableArray array];
[points addObject:[ NSValue valueWithCGPoint:CGPointMake(1,2)]];
for(NSValue *v in points) {
CGPoint p = v.CGPointValue;
//do something
}
( not tested in XCode )
This should do it:
for (NSUInteger i=0; i < sizeof(cgpointarray)/sizeof(CGPoint); i++) {
CGPoint point = cgpointarray[i];
// Do stuff with point
}
I would normally go for the NSValue approach above but sometimes you are working with an API where you can't change the output. #Andrews approach is cool but I prefer the simplicity of .count:
NSArray* arrayOfStructyThings = [someAPI giveMeAnNSArrayOfStructs];
for (NSUInteger i = 0; i < arrayOfStructyThings.count; ++i) {
SomeOldStruct tr = arrayOfStructyThings[i];
.... do your worst here ...
}

Array of arrays with ints

How would you go about storing a 2 dimensional array of ints as a class variable?
If you want an array of ints you go:
Class declaration
int * myInts;
Implementation
int ints[3] = {1,2,3};
myInts = ints;
But what if you want to store an array of arrays with ints?
Like this:
int ints[3][3] = {{1,2,3}, {1,2,3}, {1,2,3}};
I don't wanna limit the size of the arrays in the class declaration so I guess I have to go with pointers, but how?
For future reference, this is my conclusion:
Class declaration
int ** ints;
Implementation
int rows = 2;
int cols = 5;
ints = (int**)malloc(rows*sizeof(int*));
ints[0] = (int*)malloc(cols*sizeof(int));
ints[0][0] = 123;
ints[0][1] = 456;
ints[0][2] = 789;
// etc
This is my own interpretation of links provided in comments and my C skills are pretty low so take that into consideration ;) Maybe there are better ways to put in multiple numbers at a time with {123,456,789} or something, but that is beyond my requirements for now!
I've wrote sample for you:
int N = 10, M = 15;
NSMutableArray *ints = [NSMutableArray arrayWithCapacity:N]; // array[N][M]
for (int i=0; i<N; i++)
{
NSMutableArray *arr = [NSMutableArray arrayWithCapacity:M];
for (int j=0; j<M; j++)
{
[arr addObject:[NSNumber numberWithInt:(i+1)*(j+1)]];
}
[ints addObject:arr];
}
// print
for (int i=0; i<[ints count]; i++)
{
NSString *line = #"";
NSMutableArray *arr = [ints objectAtIndex:i];
for (int j=0; j<[arr count]; j++)
line = [NSString stringWithFormat:#"%# %#", line, [arr objectAtIndex:j]];
NSLog(#"%#", line);
}
If you want to dynamically allocate memory, in other words define the size of the arrays at runtime, then you need to declare the array as a pointer, malloc it, and then add another array of ints to each index at runtime. You can't really declare and dynamically allocate at the class level. If you are using cocoa/iphone sdk you can use NSMutableArray.
You could also create your own class that constructs a two dimensional array and exposes methods to push and pop int objects like [IntegerArray push:x,y,n];
Here's and example of using a double reference as Daniel R Hicks pointed out.

float [] array problem in objective c

I am coding in xcode by objective c. I came up with a problem.
I want to try like
declare float[] weights;
results looks like this
weight[0] = 0.5
weight[1] = 0.4
weight[2] = 0.9
A.h
NSMutableArray *weight;
A.m
weights = [NSMutableArray array];
for(int i=0; i < 4; i++) {
float randomNumber = arc4random() % 11;
[weights addObject:[[NSNumber alloc] initWithFloat:randomNumber]];
NSLog(#" for loops color prob weghts=%f",[weights objectAtIndex:i] );
}
I don't know what is wrong with this code. Please help me to find out?
When I print it by NSLOG " all [weight = 0.000] and also How do I access like [weight floatvalue].
secondly, when I create this class to another class there are weight [0],[1],[2],[3] and no values
It should be [[weights objectAtIndex:i] floatValue] when you print it in your NSLog
NSNumber is a class, not a integral type.
Therefore, you must use %#, not %f.
NSLog(#" for loops color prob weghts=%#",[weights objectAtIndex:i] );
Alternatively, use floatValue, like you said. You may need to cast the object into NSNumber first (for type safety)
NSNumber *number = (NSNumber *)[weights objectAtIndex:i];
NSLog(#" for loops color prob weghts=%f", [number floatValue]);
Also, you are leaking objects here, because you did not release them after putting them in the array. Either release after placing them in array, or use [NSNumber numberWithFloat:]